home *** CD-ROM | disk | FTP | other *** search
/ Cream of the Crop 22 / Cream of the Crop 22.iso / program / tdk_v120.zip / DOORKIT1.PAS < prev    next >
Pascal/Delphi Source File  |  1996-07-23  |  71KB  |  1,992 lines

  1. {
  2.  ▀▀▀▀▀▀▀▀  ▀▀▀▀▀▀    ▀▀   ▀▀
  3.    ▀▀     ▀▀   ▀▀   ▀▀  ▀▀
  4.   ▀▀     ▀▀   ▀▀▀  ▀▀▀▀▀  The DoorKit!
  5.  ▀▀     ▀▀   ▀▀   ▀▀  ▀▀
  6. ▀▀     ▀▀▀▀▀▀    ▀▀    ▀▀
  7. The BBS Door Development Kit By The People - For The People!
  8.  
  9.  
  10.    Feel free to modify or optimize this code at will. All I ask is that if
  11.    find a better way to do things (and you will), please send me a copy of
  12.    your modifications. Thanks in advance!....Larry L. Athey....
  13.  
  14.    This is the primary DoorKit unit with all the critical SIO functions.
  15.    This unit also contains all of the main door variables and constants.}
  16.  
  17. {$A+,B-,D+,E+,F-,G-,I-,L+,N-,O-,P-,Q-,R-,S+,T-,V+,X+}
  18. {$M 65520,0,655360}
  19. UNIT DOORKIT1;
  20.  
  21. INTERFACE
  22.  
  23. USES _EXIT, CRT, DOS, ASYNC, FOSUNIT;
  24.  
  25. TYPE ControlFile  = RECORD     {Record of settings for each node}
  26.      Month        : WORD;      {The Month, Day, Year variables may be used at}
  27.      Day          : WORD;      {the programmers discretion. I use them in}
  28.      Year         : WORD;      {some doors to keep track of maintenance}
  29.      SFirst       : STRING[20];{Sysop first name}
  30.      SLast        : STRING[20];{Sysop last name}
  31.      SysSec       : WORD;      {Sysop security level on the BBS}
  32.      BBSname      : STRING[40];{The name of the BBS}
  33.      SerialNumber : STRING[10];{Use this if you issue serial numbers}
  34.      HomePath     : STRING[12];{BBS software home path, I use it for Shotgun}
  35.      UseFossil    : BOOLEAN;   {Use FOSSIL comm routines Yes/No}
  36.      PortSpeed    : LONGINT;   {Locked port speed (38000 max for FOSSIL)}
  37.      UseFIFOS     : BOOLEAN;   {Use FIFOs Yes/No}
  38.      WordSize     : BYTE;      {Data Bits (Normally set to 8)}
  39.      Parity       : CHAR;      {Parity O]dd E]ven N]one (Normally set to N)}
  40.      StopBits     : BYTE;      {Stop Bits (Normally set to 1)}
  41.      InBuffer     : WORD;      {Input buffer size (Default 512)}
  42.      OutBuffer    : WORD;      {Output buffer size (Default 1024)}
  43.      NSP          : BOOLEAN;   {Non-Standard port settings Yes/No}
  44.      Port         : BYTE;      {Comport number}
  45.      IRQ          : BYTE;      {Comport IRQ}
  46.      HexAddr      : STRING[4]; {Comport Hex address}
  47.      END;
  48.     {NOTE: Not all settings in the control files are required. They are just
  49.            there in case you find a need for them. Adjust as needed....}
  50.  
  51. TYPE ColorScheme = RECORD    {Record of system colors, expand this at will.}
  52.      Hfg,                    {Window header foreground}
  53.      Hbg,                    {Window header background}
  54.      Wbg,                    {Window background}
  55.      Sfg,                    {Window shadow foreground}
  56.      Sbg,                    {Window shadow background}
  57.      Wh,                     {Window highlight color}
  58.      Wl,                     {Window lowlight color}
  59.      Ffg,                    {Input field text foreground}
  60.      Fbg,                    {Input field text background}
  61.      Bfg,                    {Input field bracket foreground}
  62.      CPBfg,                  {CPrompt bracket foreground}
  63.      CPBbg,                  {CPrompt bracket background}
  64.      CPKfg,                  {CPrompt hotkey foreground}
  65.      CPKbg,                  {CPrompt hotkey background}
  66.      CPTfg,                  {CPrompt text foreground}
  67.      CPTbg,                  {CPrompt text background}
  68.      TxFG,                   {Text reader foreground}
  69.      TxBG : BYTE;            {Text reader background}
  70.      END;
  71.  
  72. TYPE tScreen    = ARRAY[0..24,0..159] OF BYTE;
  73.      tSystemEnv = (NoTasker,DDOS,DV,WIN,OS2,Network);
  74.      tWhichIO   = (FossilIO,InternalIO);
  75.     {------------------------------------------------------------------------}
  76.     tDoor       = RECORD     {Record for the Door-System variables}
  77.     UserName    : STRING[40];{User's real name}
  78.     Alias       : STRING[40];{User's alias name}
  79.     PassWord    : STRING[40];{User's password}
  80.     UserCity    : STRING[40];{User's location}
  81.     Phone       : STRING[15];{User's home/voice phone number}
  82.     WorkPhone   : STRING[15];{User's work/data phone number}
  83.     BBSname     : STRING[40];{The name of the BBS}
  84.     Access      : WORD;      {User's security level}
  85.     UserNumber  : WORD;      {User's record number}
  86.     Event       : INTEGER;   {Minutes until next event}
  87.     {------------------------------------------------------------------------}
  88.     Comport     : BYTE;      {Which Comport the program is using; 0=local}
  89.     BaudRate    : LONGINT;   {Baudrate for the comport}
  90.     WhichIO     : tWhichIO;  {Which IO routines to use (fossil or internal)}
  91.     IOinstalled : BOOLEAN;   {comport IO routines installed?}
  92.     InBufSize   : WORD;      {Input buf size. (only for internal routines)}
  93.     OutBufSize  : WORD;      {Output buf size. (only for internal routines)}
  94.     IRQ         : BYTE;      {Which IRQ is being used}
  95.     WordSize    : BYTE;      {Wordsize (Data Bits) for comport}
  96.     Parity      : CHAR;      {Parity for comport; 'N'=none 'E'=even 'O'=odd}
  97.     StopBits    : BYTE;      {Stop Bits for comport}
  98.     Node        : BYTE;      {Which node the user is on}
  99.     {------------------------------------------------------------------------}
  100.     LocalInputON: BOOLEAN;   {Enable/Disable local keyboard input}
  101.     UpdateLocal : BOOLEAN;   {Writes to the local screen are allowed or not?}
  102. {*} UpdateStatusBar: BOOLEAN;{Update status bar? (even if updatelocal=false)}
  103. {*} UseVirtScr  : BOOLEAN;   {Use the virtual screen?}
  104.     StatusBarY  : BYTE;      {What line the status bar is displayed on}
  105.     LocalMaxY   : BYTE;      {# of lines (1-#) to update on local screen (usually 25)}
  106.     {------------------------------------------------------------------------}
  107.     SecondsLeft : LONGINT;   {Seconds Left until user is booted back to BBS}
  108.     MinutesLeft : LONGINT;   {Minutes Left until user is booted back to BBS}
  109. {!} IdleCount   : INTEGER;   {How many seconds the user has been inactive}
  110.     UpdateSecs  : BOOLEAN;   {Update the user's remaining time?}
  111.     UpdateIdle  : BOOLEAN;   {Ckeck for user inactivity?}
  112. {*} LocalKey    : BOOLEAN;   {Was the last key pressed local?}
  113.     OnLine      : BOOLEAN;   {Is user online/connected?}
  114.     {------------------------------------------------------------------------}
  115.     END;
  116. {*  Variables marked with an asterisk are "Read-Only" and should never be
  117.     modified or altered by your code. AGAIN! - DO NOT TAMPER WITH THESE!}
  118.  
  119. {!  The IdleCount variable could cause you problems if you are writing any
  120.     kind of a door that forces the user to sit there without entering a key.
  121.     If any procedure or function in your program takes more than 300 seconds
  122.     to complete, you may want to add a hook in there to set this variable to
  123.     zero every once in a while. An example would be in an offline mail door,
  124.     every time the program packs one message add a DoorSys.IdleCount := 0;..}
  125.  
  126. CONST
  127.   VirtScr        : ^tScreen = NIL; {Virtual Screen Record}
  128.   VirtX          : INTEGER = 1;    {Virtual X cursor position}
  129.   VirtY          : INTEGER = 1;    {Virtual Y cursor position}
  130.   WrapInput      : BOOLEAN = FALSE;{Word wrap input fields Y/N?}
  131.   Local          : BOOLEAN = TRUE; {Are we running in local mode?}
  132.   Tty            = 0;
  133.   Ansi           = 1;
  134.   Avatar         = 2;
  135.   Rip            = 3;
  136.   Max            = 4;
  137.   Graphics       : BYTE    = Ansi; {Remote caller's graphics protocol}
  138.   UseDoorSys     : BOOLEAN = TRUE; {Allow door to read DOOR.SYS?}
  139.   UseDorInfo     : BOOLEAN = TRUE; {Allow door to read DORINFO#.DEF?}
  140.   _HangUp        : BOOLEAN = FALSE;{Lower DTR before terminating?}
  141.   HideParams     : BOOLEAN = FALSE;{Hide information when exiting door?}
  142.   UseTTY         : BOOLEAN = FALSE;{Allow ASCII/TTY caller in the door?}
  143.   KillDrop       : BOOLEAN = FALSE;{Delete drop file before terminating?}
  144.   Shotgun        : BOOLEAN = FALSE;{Is this a Shotgun BBS system?}
  145.   IntConfig      : BOOLEAN = FALSE;{Use internal configuration program?}
  146.   UseLocal       : BOOLEAN = TRUE; {Allow local operation of the door?}
  147.   UseLog         : BOOLEAN = FALSE;{Use activity logging?}
  148.   UseAd          : BOOLEAN = TRUE; {Display program Ad upon startup?}
  149.  
  150. TYPE CursorMoveType = RECORD
  151.   Up     : ARRAY[Tty..Avatar] OF STRING[3];
  152.   Down   : ARRAY[Tty..Avatar] OF STRING[3];
  153.   Right  : ARRAY[Tty..Avatar] OF STRING[3];
  154.   Left   : ARRAY[Tty..Avatar] OF STRING[3];
  155.   Home   : ARRAY[Tty..Avatar] OF STRING[3];
  156.   Endkey : ARRAY[Tty..Avatar] OF STRING[3];
  157.   Insert : ARRAY[Tty..Avatar] OF STRING[3];
  158.   Delete : ARRAY[Tty..Avatar] OF STRING[3];
  159. END;
  160.  
  161. CONST
  162.   CursorMove : CursorMoveType = (Up     : (#0+#72,#27'[A',#22+#3);
  163.                                  Down   : (#0+#80,#27'[B',#22+#4);
  164.                                  Right  : (#0+#77,#27'[C',#22+#6);
  165.                                  Left   : (#0+#75,#27'[D',#22+#5);
  166.                                  Home   : (#0+#71,#27'[H',#22+#0);
  167.                                  EndKey : (#0+#79,#27'[K',#22+#0);
  168.                                  Insert : (#0+#82,#22,#22);
  169.                                  Delete : (#0+#83,#127,#127));
  170. VAR
  171.   CurTime       : DATETIME;   {The Current Time}
  172.   DropFilePath  : STRING[80]; {Path to drop files}
  173.   Ctl           : ControlFile;{Record for storing door setups per node}
  174.   CS            : ColorScheme;{Record for storing various system colors}
  175.   DoorSys       : tDoor;      {Door-System variables}
  176.   StartTime     : DATETIME;   {When user entered door}
  177.   SystemEnv     : tSystemEnv; {What OS is operating locally?}
  178.   BackSpaceChar : CHAR;       {Character to use when the BS key is pressed}
  179.   LengthScr     : BYTE;       {Length of the remote caller's screen}
  180.   LogPath       : STRING[80]; {Path to write activity log file}
  181.   LogFile       : STRING[40]; {Activity log file name (Room for variables)}
  182.   UFirst        : STRING[20]; {User's first name}
  183.   ULast         : STRING[20]; {User's last name}
  184.   Insert1       : STRING[20];
  185.   Insert2       : STRING[20];
  186.   Insert3       : STRING[20];
  187.   Insert4       : STRING[20];
  188.   Insert5       : STRING[20]; {Various "Static" global system variables}
  189.   s_ReadKey     : STRING[2];  {Local storage for sReadKey extended keys}
  190.   MaxID         : STRING[4];  {For future development}
  191.  
  192. {─--[Headers]-──────────────────────────────────────────────────────────────}
  193.  
  194. PROCEDURE InitDoorKit;
  195. {^ This procedure is like a "DO-ALL" procedure for starting up a door. This
  196.    eliminates the need for you to make a whole string of spaghetti at the
  197.    beginning of your program. Just set what ever variables you want that to
  198.    change from their default vaules (if needed) then call this procedure.}
  199. PROCEDURE ReadCTL;
  200. {^ This is used to read the settings for each node into the program and is
  201.    called automatically by InitDoorKit.}
  202. PROCEDURE StartUpLog;
  203. {^ This procedure is automatically called in the InitDoorKit procedure.
  204.    However, some people may choose to use node specific log files which
  205.    requires you to define your log file and path AFTER The DoorKit has
  206.    been initialized. You can then call this procedure AFTER The DoorKit
  207.    has been initialized and AFTER you have defined your LogFile/LogPath.}
  208. PROCEDURE UpdateTime;
  209. {^ If your door is busy (ie: Not at an sReadkey/sKeyPressed prompt) you will
  210.    want to occasionally call this procedure to be sure to update the user's
  211.    time. It would be best to call this procedure like every 5 or 10 seconds
  212.    so your program doesn't have to slow down for this procedure. Even if you
  213.    only call it every 10 seconds, 10 seconds will still be deducted from the
  214.    user's time. Be sure to see the variable DoorSys.IdleCount as well.}
  215. FUNCTION InitComport : BOOLEAN;
  216. {^ Initializes the comport for IO. This is normally the 2nd thing that is
  217.    called when your door starts (the 1st thing would either be reading a
  218.    DropFile, or INI file, or both). This must be called before any of the
  219.    other comport IO routines are called! (any procs. that use the modem).
  220.    No params are needed because all the values needed are taken from the
  221.    DoorSys record (Port,Baud,Parity), Set up all DoorSys variables first!
  222.    This isn't needed if you are using the InitDoorKit procedure.}
  223. PROCEDURE DeInitComport;
  224. {^ DeInitializes the comport. You can call this at the end of your door, but
  225.    you don't have to. It will be called automatically on its own at the end
  226.    of the program, its better if you don't call it. (see also: AddToExitChain)}
  227. PROCEDURE ChangeIRQ(Comport,IRQ : BYTE);
  228. {^ Assigns the IRQ for the comport. This is for comports that use nonstandard
  229.    IRQ only, if its a standard IRQ, then you don't need to call this. If this
  230.    ever needs to be called, it must be called before InitComport!
  231.    (This only works for the InternalIO!)}
  232. PROCEDURE ChangeFIFO(Comport : BYTE; On : BOOLEAN);
  233. {^ Lets you toggle the use of the receive FIFOs on the modem. By default the
  234.    FIFOs will NOT be used. That is to avoid the conficts with some modems
  235.    that have buggy FIFO's. Chances are that, this can be turned on without
  236.    any problems, most modems (if not all) these days have good FIFO buffers,
  237.    but some older or substandard ones might not.}
  238. FUNCTION Carrier : BOOLEAN;
  239. {^ Returns True if User is Connected, false if not. If DoorSys.Comport = 0
  240.    (local mode) then this will always return true.}
  241. PROCEDURE Lower_DTR;
  242. {^ Lowers the DTR (Drops Carrier) on the user.}
  243. FUNCTION DataAvailable : BOOLEAN;
  244. {^ Returns true if there is data available in the modem buffer.}
  245. PROCEDURE TimeSlice;
  246. {^ Gives up remaining CPU time to the rest of the OS. This procedure is set
  247.    up in the sReadkey function already, along with a few other procedures.
  248.    You can use it for your own needs as well.}
  249. PROCEDURE BeginCritical;
  250. {^ Begins a "Critical" block. After calling this under Multi-Tasking systems,
  251.    the majority of the CPU time will be given to your program, until you call
  252.    "EndCritical". This should be called right before sections of code that
  253.    need your program to be as smooth as possible. (If your not running under
  254.    a Multi-Tasking system, then this does nothing)}
  255. PROCEDURE EndCritical;
  256. {^ Ends a "Critical" block. This should be called after a call has been made
  257.    to "BeginCritical" and your critical section is done. (it does no harm if
  258.    BeginCritical was not called before this). Be sure to call this at some
  259.    point if you do call BeginCritical!  Otherwise you'll probably slow down
  260.    the rest of the system until your door exits.}
  261. PROCEDURE SendStr(S : STRING);
  262. {^ This is used to send a string of data directly to the comport thus
  263.    bypassing any output to the local screen.}
  264. PROCEDURE sCursorUp(N : BYTE);
  265. PROCEDURE sCursorDown(N : BYTE);
  266. PROCEDURE sCursorLeft(N : BYTE);
  267. PROCEDURE sCursorRight(N : BYTE);
  268. {^ Move the cursor n times in a any direction. If the cursor is already at
  269.    the maximum or minimum position in the direction its moving, it will not
  270.    move any further. This will only work if ANSI is enabled, otherwise any
  271.    calls to this procedure will be ignored.}
  272. PROCEDURE sClrscr;
  273. {^ Clears the screen with the current attribute.}
  274. PROCEDURE sClrEol;
  275. {^ Clears the current line starting from the current cursor position, to the
  276.    end of the line, w/o moving the cursor.....This happens on the remote and
  277.    local screen (according to UpdateLocal)....This will only work if ANSI is
  278.    enabled, otherwise any calls to this procedure will be ignored.}
  279. PROCEDURE sGotoXY(X,Y : BYTE);
  280. {^ Moves the cursor to the values in X,Y on the remote, and local screen
  281.    (according to UpdateLocal). The valid ranges are: X=1..80; Y=1..NumLines,
  282.    if either value is over the max range nothing will happen. This will only
  283.    work if ANSI is enabled.}
  284. PROCEDURE FlushOutput;
  285. {^ Flushes the output buffer. This procedure does not return until all the
  286.    output in the buffer has been sent to the remote.}
  287. PROCEDURE PurgeOutPut;
  288. {^ Purges all output in the Output buffer. Anything in the buffer is not
  289.    displayed (or sent to remote).}
  290. PROCEDURE PurgeInput;
  291. {^ Clears all input in the input buffer. Anything in the buffer will not be
  292.    read by the input routines.}
  293. PROCEDURE sWriteC(C : CHAR);
  294. PROCEDURE sWritelnC(C : CHAR); {append CRLF after the character}
  295. {^ Writes a character to the comport, and the local screen (if UpdateLocal is
  296.    true).}
  297. PROCEDURE sWriteN(N : LONGINT);
  298. PROCEDURE sWritelnN(N : LONGINT); {append CRLF after the number}
  299. {^ Writes any whole number to the comport, and the local screen (according to
  300.    UpdateLocal). You can use shortint,byte,integer,word & longints with this.
  301.    (You can also use: write(IO,'The Number is: ',mynumber)}
  302. PROCEDURE sWrite(S : STRING);
  303. PROCEDURE sWriteln(S : STRING); {append CRLF after the string}
  304. {^ Writes a string to the comport, and the local screen (according to
  305.    UpdateLocal).}
  306. FUNCTION sKeyPressed : BOOLEAN;
  307. {^ Returns True if a local key has been pressed (if LocalInputON), or if a
  308.    key is waiting in the Input buffer (from remote).}
  309. PROCEDURE sWaitInput(Ms : INTEGER);
  310. {^ Waits for a keypress, or Ms milliseconds. Accurate to 10 milliseconds.}
  311. FUNCTION sReadKey : CHAR;
  312. {^ Reads either the first key in the INPUT buffer from the comport, or if a
  313.    local key was pressed. The scan code returned is just like TP's readkey.
  314.    (except Function keys (F1-F12, AltF1-AltF12))}
  315. FUNCTION AnsiColor : STRING;
  316. PROCEDURE SetFore(Fore : BYTE);
  317. PROCEDURE SetBack(Back : BYTE);
  318. PROCEDURE Set_Color(Fore,Back : BYTE);
  319. {^ Sets the foreground and background colors to the values given. These
  320.    Procedures WILL actually send the ansi codes needed to change the color
  321.    to the remote screen, and change TextAttr locally. Repetetive color
  322.    changes of the same foreground and background are filtered from being
  323.    sent to the comport automatically (Makes for faster drawing).}
  324. PROCEDURE ShowStatusBar;
  325. {^ This redraws the Local Status Bar, but will not update the time variable
  326.    on the bar. This sets a window() so that the 25th line will not be
  327.    disturbed by the normal IO routines. If you want to write to the status
  328.    bar, then use the WriteStr() proc in the DOORIO unit. This will set
  329.    UpdateStatusBar := True.}
  330. PROCEDURE HideStatusBar;
  331. {^ This hides the Local Status Bar. This resets the window() so that the
  332.    25th line can be written to with the SIO routines. This will set
  333.    UpdateStatusBar := False.}
  334. PROCEDURE Wait(Seconds : WORD);
  335. {^ Wait a number of seconds. Seconds is not just an approximation like TP's
  336.    Delay procedure. This also does Time Slicing while waiting.}
  337. FUNCTION InitVirtScr : BOOLEAN;
  338. {^ Sets up the virtual screen to be used and sets the DoorSys variable for
  339.    it also. This virtual screen is maintained by all the output routines in
  340.    this library. When ever something is displayed to the player it is also
  341.    written to the virtual screen. When initializing the virtual screen,
  342.    After you call this function you should clear the screen (with a call to
  343.    sClrScr) to be sure that the screens get synchronized. This feature can
  344.    be useful for a couple of reasons: 1) This allows the user to "Refresh"
  345.    his/her screen anywhere in the door, if their screen gets garbled from
  346.    line noise or something. 2) If the door is running in Sysop Blockout Mode
  347.    (ie: nothing is being drawn to the local screen) and at some point the
  348.    door comes out of that mode, allowing the sysop to see what's going on
  349.    again...The door can update the local screen immediately. The only real
  350.    drawback to these routines is that they slow down the normal output
  351.    routines in this library, But it probably won't be noticable to anyone.}
  352. PROCEDURE FreeVirtScr;
  353. {^ Frees the Virtual Screen, and sets the DoorSys variable to reflect it.
  354.    After a call to this the Virtual Screen is not used, and will be a NIL
  355.    pointer if you try to access it. This is called automatically when the
  356.    program exits, so you don't have to call it.}
  357. PROCEDURE DrawScr(Scr : POINTER; X1,Y1,X2,Y2 : BYTE);
  358. {^ Refreshes the remote and local screens using the Virtual Screen. So that
  359.    must of been initialized first. Scr is a pointer to a buffer that holds
  360.    the screen. It must point to an array of tScreen, X1,Y1,X2,Y2 is the
  361.    rectangle to draw. The very last char in the bottom corner (80,25) will
  362.    NEVER be drawn. Otherwise the screen will scroll up.}
  363. PROCEDURE AutoDetect;
  364. {^ This proceudre is used to detect the remote graphics capabilities and
  365.    screen length. Note that the screen length may not be 100% accurate
  366.    due to the variations in terminal program design. This procedure also
  367.    detects the local operating system as well.}
  368. PROCEDURE FakeVirus;
  369. {^ Displays a bogus Telix file download screen that appears to transfer the
  370.    file VIRUS.COM to the user's C:\ directory and then drops carrier on them.
  371.    This is mainly for getting rid of problem users from the system. <G>}
  372. PROCEDURE SplitUserName;
  373. {^ In some cases you may need to change the DoorSys.UserName....After you do
  374.    that, you will need to refill the UFirst and ULast variables. That's what
  375.    this procedure does for you.}
  376. PROCEDURE ReadDorInfo(DoorFn : PathStr; VAR DropInfo : tDoor);
  377. {^ Reads a DORINFO#.DEF drop file into the DoorSys record.}
  378. PROCEDURE ReadDoorSys(DoorFn : PathStr; VAR DropInfo : tDoor);
  379. {^ Reads a DOOR.SYS drop file into the DoorSys record.}
  380. PROCEDURE ShellToDos;
  381. {^ *Just as it says, it shells the program to DOS.}
  382. FUNCTION  LocateFile(FName : STRING) : STRING;
  383. {^ Locates a file in the DOS PATH and returns the full path & file name.}
  384. PROCEDURE _Execute(FName,Params : STRING);
  385. {^ *Runs an external executable/com with no screen save.}
  386. PROCEDURE Execute(FName,Params : STRING);
  387. {^ *Runs an exteral executable/com with text screen save.}
  388. PROCEDURE RunBatFile(TheBat : STRING);
  389. {^ *Runs a batch file with text screen save.}
  390. {  *NOTE: When these processes run, only a 1.2K footprint of the program
  391.           is left in memory giving you the most RAM for child processes.}
  392.  
  393. IMPLEMENTATION
  394.  
  395. USES _SIO, EXEC, DOORKIT2;
  396.  
  397. CONST
  398.   F1 = #59; F2 = #60; F3 = #61; F4 = #62; F5 = #63;
  399.   F6 = #64; F7 = #65; F8 = #66; F9 = #67; F10 = #68;
  400.   AltF1 = #104; AltF2 = #105; AltF3 = #106; AltF4 = #107; AltF5 = #108;
  401.   AltF6 = #109; AltF7 = #110; AltF8 = #111; AltF9 = #112; AltF10 = #113;
  402.   {^ These are the constants for your sysop function keys. There is no
  403.      way for the remote to send these keys to your door.}
  404.  
  405. VAR
  406.   Buffer      : ARRAY[1..4000] OF BYTE;
  407.   CurColor    : BYTE;
  408.   ClockResult : LONGINT;
  409.   StopClock   : LONGINT;
  410.   StartClock  : LONGINT;
  411.  
  412. {───────────────────────────────────────────────────────────────────────────}
  413. PROCEDURE ClockOn;
  414. VAR
  415.   S100 : WORD;
  416. BEGIN
  417.   WITH CurTime DO BEGIN
  418.     GETTIME(Hour,Min,Sec,S100);
  419.     StartClock := (Hour * 3600) + (Min * 60) + Sec;
  420.   END;
  421. END;
  422. {───────────────────────────────────────────────────────────────────────────}
  423. PROCEDURE ClockOff;
  424. VAR
  425.   S100 : WORD;
  426. BEGIN
  427.   WITH CurTime DO BEGIN
  428.     GETTIME(Hour,Min,Sec,S100);
  429.     StopClock := (Hour * 3600) + (Min * 60) + Sec;
  430.   END;
  431. END;
  432. {───────────────────────────────────────────────────────────────────────────}
  433. PROCEDURE UpdateTime;
  434. BEGIN
  435.   ClockOff;
  436.   ClockResult := (StopClock - StartClock);
  437.   WITH DoorSys DO BEGIN
  438.     IF NOT Carrier THEN BEGIN
  439.       ErrLevel := 3;
  440.       HALT(ErrLevel);
  441.     END;
  442.     IF UpdateIdle THEN BEGIN
  443.       INC(IdleCount,ClockResult);
  444.       IF IdleCount = 300 THEN BEGIN {Halt for 5 minutes of user inactivity}
  445.         ErrLevel := 5;
  446.         HALT(ErrLevel);
  447.       END ELSE IF IdleCount = 60 THEN BEGIN {Wake-Up the caller after 60 secs}
  448.         IF NOT Local THEN SendStr(^G) ELSE WRITE(^G);
  449.       END;
  450.     END;
  451.     IF UpdateSecs THEN BEGIN
  452.       DEC(SecondsLeft,ClockResult);
  453.       IF SecondsLeft <= 0 THEN BEGIN
  454.         ErrLevel := 4;
  455.         HALT(ErrLevel);
  456.       END;
  457.       MinutesLeft := SecondsLeft DIV 60;
  458.     END;
  459.   END;
  460.   ClockOn;
  461. END;
  462. {───────────────────────────────────────────────────────────────────────────}
  463. FUNCTION InitComport;
  464. VAR
  465.   B : BOOLEAN;
  466. BEGIN
  467.   InitComport := FALSE;
  468.   IF DoorSys.IOinstalled THEN EXIT;
  469.   DoorSys.IOinstalled := TRUE;
  470.   B := FALSE;
  471.   WITH DoorSys DO IF Comport > 0 THEN BEGIN
  472.     CASE WhichIO OF
  473.       InternalIO : BEGIN
  474.                      B := OpenCom(Comport,InBufSize,OutBufSize);
  475.                      IF B THEN ComParams(Comport,BaudRate,WordSize,Parity,StopBits)
  476.                    END;
  477.       FossilIO   : BEGIN
  478.                      B := F_Init(Comport);
  479.                      IF B THEN BEGIN
  480.                        F_Parms(Comport,BaudRate,WordSize,Parity,StopBits);
  481.                        F_Flow(Comport,TRUE);
  482.                      END;
  483.                    END;
  484.     END;
  485.   END ELSE B := TRUE;
  486.   IF NOT B THEN BEGIN
  487.     ErrLevel := 1;
  488.     ErrorLog('Cannot Initialize Comport!',ErrLevel,TRUE);
  489.   END;
  490.   DoorSys.IOinstalled := B;
  491.   IF (Not Carrier) THEN B := FALSE
  492.                    ELSE BEGIN
  493.                      PurgeOutput;
  494.                      PurgeInput;
  495.                    END;
  496.   InitComport    := B;
  497.   DoorSys.Online := B;
  498. END;
  499. {───────────────────────────────────────────────────────────────────────────}
  500. PROCEDURE DeInitComport;
  501. BEGIN
  502.   IF NOT DoorSys.IOinstalled THEN EXIT;
  503.   WITH DoorSys DO IF (Comport > 0) THEN
  504.     CASE WhichIO OF
  505.       InternalIO : BEGIN
  506.                      SetRTSmode(Comport,FALSE,0,0);
  507.                      SetCTSmode(Comport,FALSE);
  508.                      CloseCom(Comport);
  509.                    END;
  510.       FossilIO   : F_Close(Comport);
  511.     END;
  512.   DoorSys.IOinstalled := FALSE;
  513.   DoorSys.Online      := FALSE;
  514. END;
  515. {───────────────────────────────────────────────────────────────────────────}
  516. FUNCTION Carrier;
  517. BEGIN
  518.   IF DoorSys.Comport > 0 THEN BEGIN
  519.     CASE DoorSys.WhichIO OF
  520.       InternalIO : Carrier := DCDstat(DoorSys.Comport);
  521.       FossilIO   : Carrier := F_CD(DoorSys.Comport);
  522.     END;
  523.   END ELSE BEGIN
  524.     Carrier := TRUE;
  525.   END;
  526. END;
  527. {───────────────────────────────────────────────────────────────────────────}
  528. PROCEDURE ChangeIRQ;
  529. BEGIN
  530.   C_PortInt[Comport] := IRQ;
  531. END;
  532. {───────────────────────────────────────────────────────────────────────────}
  533. PROCEDURE ChangeFIFO;
  534. BEGIN
  535.   C_FifoOK[Comport] := On;
  536. END;
  537. {───────────────────────────────────────────────────────────────────────────}
  538. FUNCTION DataAvailable : BOOLEAN;
  539. BEGIN
  540.   DataAvailable := False;
  541.   WITH DoorSys DO BEGIN
  542.     CASE WhichIO OF
  543.       InternalIO : DataAvailable := ComBufferLeft(Comport,'I') > 0;
  544.       FossilIO   : DataAvailable := F_Avail(Comport);
  545.     END;
  546.   END;
  547. END;
  548. { ────────────────────────────────────────────────────────────────────────── }
  549. PROCEDURE Lower_DTR;
  550. VAR
  551.   Regs : REGISTERS;
  552.   Loop : BYTE;
  553. BEGIN
  554.   sWriteln(''); sWriteln('');
  555.   OutTxt(15,4,' CLICK! ');
  556.   IF Local THEN EXIT;
  557.   ErrLevel := 3;
  558.   Loop := 0;
  559.   REPEAT
  560.     INC(Loop);
  561.     Regs.DX := (DoorSys.ComPort - 1); {COM1=0, COM2=1, COM3=2, COM4=3}
  562.     Regs.AL := $00;
  563.     Regs.AH := $06;
  564.     INTR($14,Regs);
  565.     Wait(1);
  566.     SendStr('~~~+++~~~ATH0');
  567.     Wait(1);
  568.   UNTIL (NOT Carrier) OR (Loop = 5);
  569. END;
  570. { ────────────────────────────────────────────────────────────────────────── }
  571. PROCEDURE DetectOS; Assembler;
  572. Asm
  573. @CheckDV :
  574.     mov   AX, $2B01
  575.     mov   CX, $4445
  576.     mov   DX, $5351
  577.     INT   $21
  578.     cmp   AL, $FF
  579.     je    @CheckDoubleDOS
  580.     mov   SystemEnv, DV
  581.     jmp   @Done
  582.  
  583. @CheckDoubleDOS :
  584.     mov   AX, $E400
  585.     INT   $21
  586.     cmp   AL, $00
  587.     je    @CheckWindows
  588.     mov   SystemEnv, DDOS
  589.     jmp   @Done
  590.  
  591. @CheckWindows :
  592.     mov   AX, $1600
  593.     INT   $2F
  594.     cmp   AL, $00
  595.     je    @CheckOS2
  596.     cmp   AL, $80
  597.     je    @CheckOS2
  598.     mov   SystemEnv, WIN
  599.     jmp   @Done
  600.  
  601. @CheckOS2 :
  602.     mov   AX, $3001
  603.     INT   $21
  604.     cmp   AL, $0A
  605.     je    @InOS2
  606.     cmp   AL, $14
  607.     jne   @CheckNetwork
  608.   @InOS2 :
  609.     mov   SystemEnv, OS2
  610.     jmp   @Done
  611.  
  612. @CheckNetwork :
  613.     mov   AX,$7A00
  614.     INT   $2F
  615.     cmp   AL,$FF
  616.     jne   @NoTasker
  617.     mov   SystemEnv, Network
  618.     jmp   @Done
  619.  
  620. @NoTasker :
  621.     mov   SystemEnv, NoTasker
  622.  
  623. @Done :
  624. END;
  625. {───────────────────────────────────────────────────────────────────────────}
  626. PROCEDURE TimeSlice;
  627. BEGIN
  628.   CASE SystemEnv OF
  629.     NoTasker : Asm INT $28 END;
  630.     DDOS     : Asm mov ax,$EE01; INT $21 END;
  631.     DV       : Asm mov ax,$1000; INT $15 END;
  632.     WIN,OS2  : Asm mov ax,$1680; INT $2F END;
  633.     Network  : Asm mov bx,$000A; INT $7A END;
  634.   END;
  635. END;
  636. {───────────────────────────────────────────────────────────────────────────}
  637. PROCEDURE BeginCritical; Assembler;
  638. Asm
  639.   cmp   SystemEnv, DV
  640.   je    @DVCrit
  641.   cmp   SystemEnv, DDOS
  642.   je    @DoubleDOSCrit
  643.   cmp   SystemEnv, WIN
  644.   je    @WinCrit
  645.   jmp   @EndCrit
  646.  
  647. @DVCrit :
  648.   mov   AX,$101B
  649.   INT   $15
  650.   jmp   @EndCrit
  651.  
  652. @DoubleDOSCrit :
  653.   mov   AX,$EA00
  654.   INT   $21
  655.   jmp   @EndCrit
  656.  
  657. @WinCrit :
  658.   mov   AX,$1681
  659.   INT   $2F
  660.   jmp   @EndCrit
  661.  
  662. @EndCrit :
  663. END;
  664. {───────────────────────────────────────────────────────────────────────────}
  665. PROCEDURE EndCritical; Assembler;
  666. Asm
  667.   cmp   SystemEnv, DV
  668.   je    @DVCrit
  669.   cmp   SystemEnv, DDOS
  670.   je    @DoubleDOSCrit
  671.   cmp   SystemEnv, WIN
  672.   je    @WinCrit
  673.   jmp   @EndCrit
  674.  
  675. @DVCrit :
  676.   mov   AX,$101C
  677.   INT   $15
  678.   jmp   @EndCrit
  679.  
  680. @DoubleDOSCrit :
  681.   mov   AX,$EB00
  682.   INT   $21
  683.   jmp   @EndCrit
  684.  
  685. @WinCrit :
  686.   mov   AX,$1682
  687.   INT   $2F
  688.   jmp   @EndCrit
  689.  
  690. @EndCrit :
  691. END;
  692. {───────────────────────────────────────────────────────────────────────────}
  693. PROCEDURE SendStr(S : STRING);
  694. BEGIN
  695.   IF Carrier THEN BEGIN
  696.     IF DoorSys.Comport > 0 THEN
  697.       CASE DoorSys.WhichIO OF
  698.         InternalIO : I_ComWrite(DoorSys.Comport,S);
  699.         FossilIO   : F_Write(DoorSys.Comport,S);
  700.       END;
  701.   END ELSE BEGIN
  702.     DoorSys.Online := FALSE
  703.   END;
  704. END;
  705. {───────────────────────────────────────────────────────────────────────────}
  706. PROCEDURE sCursorUp;
  707. VAR
  708.   S : STRING[3];
  709. BEGIN
  710.   WITH DoorSys DO IF (Graphics <> TTY) AND (VirtY > 1) THEN BEGIN
  711.     IF N > 1 THEN STR(N,S) ELSE S := '';
  712.     SendStr(#27'['+S+'A');
  713.     DEC(VirtY,N);
  714.     IF VirtY < 1 THEN VirtY := 1;
  715.     IF UpdateLocal THEN BEGIN
  716.       GOTOXY(VirtX,WhereY-N);
  717.       IF (VirtY <= DoorSys.LocalMaxY) THEN ShowCursor;
  718.     END;
  719.   END;
  720. END;
  721. {───────────────────────────────────────────────────────────────────────────}
  722. PROCEDURE sCursorDown;
  723. VAR
  724.   S : STRING[3];
  725. BEGIN
  726.   WITH DoorSys DO IF (Graphics <> TTY) AND (VirtY < 25) THEN BEGIN
  727.     IF N > 1 THEN STR(N,S) ELSE S := '';
  728.     SendStr(#27'['+S+'B');
  729.     INC(VirtY,N);
  730.     IF VirtY > 25 THEN VirtY := 25;
  731.     IF UpdateLocal THEN BEGIN
  732.       GOTOXY(VirtX,WhereY+N);
  733.       IF (VirtY > DoorSys.LocalMaxY) THEN HideCursor;
  734.     END;
  735.   END;
  736. END;
  737. {───────────────────────────────────────────────────────────────────────────}
  738. PROCEDURE sCursorRight;
  739. VAR
  740.   S : STRING[3];
  741. BEGIN
  742.   WITH DoorSys DO IF (Graphics <> TTY) AND (VirtX < 80) THEN BEGIN
  743.     IF N > 1 THEN STR(N,S) ELSE S := '';
  744.     SendStr(#27'['+S+'C');
  745.     INC(VirtX,N);
  746.     IF VirtX > 80 THEN VirtX := 80;
  747.     IF UpdateLocal THEN GOTOXY(VirtX,VirtY);
  748.   END;
  749. END;
  750. {───────────────────────────────────────────────────────────────────────────}
  751. PROCEDURE sCursorLeft;
  752. VAR
  753.   S : STRING[3];
  754.   I : BYTE;
  755. BEGIN
  756.   WITH DoorSys DO IF (Graphics <> TTY) AND (VirtX > 1) THEN BEGIN
  757.     IF N > 80 THEN N := 80;
  758.     IF N > 1 THEN STR(N,S) ELSE S := '';
  759.     SendStr(#27'['+S+'D');
  760.     DEC(VirtX,N);
  761.     IF VirtX < 1 THEN VirtX := 1;
  762.     IF UpdateLocal THEN GOTOXY(VirtX,VirtY);
  763.   END;
  764. END;
  765. {───────────────────────────────────────────────────────────────────────────}
  766. PROCEDURE sClrScr;
  767. BEGIN
  768.   WITH DoorSys DO BEGIN
  769.     IF Graphics = TTY THEN SendStr(#12) ELSE SendStr(#27'[2J');
  770.     IF UpdateLocal THEN CLRSCR;
  771.   END;
  772.   VirtX := 1;
  773.   VirtY := 1;
  774.   IF DoorSys.UseVirtScr THEN FillWord(VirtScr^,SIZEOF(VirtScr^),TextAttr,' ');
  775. END;
  776. {───────────────────────────────────────────────────────────────────────────}
  777. PROCEDURE sClrEol;
  778. BEGIN
  779.   WITH DoorSys DO IF Graphics <> TTY THEN BEGIN
  780.     SendStr(#27'[K');
  781.     IF UpdateLocal THEN CLREOL;
  782.   END;
  783.   IF DoorSys.UseVirtScr THEN FillWord(VirtScr^[VirtY-1,(VirtX-1)*2],(80-VirtX+1)*2,TextAttr,' ');
  784. END;
  785. {───────────────────────────────────────────────────────────────────────────}
  786. PROCEDURE sGotoXY;
  787. BEGIN
  788.   WITH DoorSys DO IF Graphics <> TTY THEN BEGIN
  789.     SendStr(#27'['+IStr(Y,0)+';'+IStr(X,0)+'H');
  790.     IF UpdateLocal THEN BEGIN
  791.       GOTOXY(X,Y);
  792.       IF (Y > DoorSys.LocalMaxY) THEN HideCursor ELSE ShowCursor;
  793.     END;
  794.   END;
  795.   IF (X > 0) AND (X < 81) THEN VirtX := X;
  796.   IF (Y > 0) AND (Y < 26) THEN VirtY := Y;
  797. END;
  798. {───────────────────────────────────────────────────────────────────────────}
  799. FUNCTION sKeyPressed;
  800. VAR
  801.   B : BOOLEAN;
  802. BEGIN
  803.   B := FALSE;
  804.   IF Carrier THEN BEGIN
  805.     IF DoorSys.Comport > 0 THEN
  806.       CASE DoorSys.WhichIO OF
  807.         InternalIO : B := ComBufferLeft(DoorSys.Comport,'I') > 0;
  808.         FossilIO   : B := F_Avail(DoorSys.Comport);
  809.       END;
  810.     IF DoorSys.LocalInputON AND (NOT B) THEN B := KEYPRESSED;
  811.   END ELSE BEGIN
  812.     DoorSys.Online := FALSE;
  813.   END;
  814.   sKeyPressed := B;
  815.   IF NOT B THEN TimeSlice;
  816. END;
  817. {───────────────────────────────────────────────────────────────────────────}
  818. PROCEDURE FlushOutput;
  819. BEGIN
  820.   IF (DoorSys.IOInstalled) AND (Carrier) THEN
  821.     CASE DoorSys.WhichIO OF
  822.       InternalIO : ComWaitForClear(DoorSys.Comport);
  823.       FossilIO   : F_Flush(DoorSys.Comport);
  824.     END;
  825. END;
  826. {───────────────────────────────────────────────────────────────────────────}
  827. PROCEDURE PurgeOutput;
  828. BEGIN
  829.   IF (DoorSys.IOInstalled) AND (DoorSys.Comport > 0) THEN
  830.   CASE DoorSys.WhichIO OF
  831.     InternalIO : ClearCom(DoorSys.Comport,'O');
  832.     FossilIO   : F_Kill_Out(DoorSys.Comport);
  833.   END;
  834. END;
  835. {───────────────────────────────────────────────────────────────────────────}
  836. PROCEDURE PurgeInput;
  837. BEGIN
  838.   IF (DoorSys.IOInstalled) AND (DoorSys.Comport > 0) THEN
  839.   CASE DoorSys.WhichIO OF
  840.     InternalIO : ClearCom(DoorSys.Comport,'I');
  841.     FossilIO   : F_Kill_In(DoorSys.Comport);
  842.   END;
  843. END;
  844. {───────────────────────────────────────────────────────────────────────────}
  845. PROCEDURE DoVirt(C : CHAR; Yinc : BYTE); {Yinc should be ONLY 0 or 1!}
  846. VAR
  847.   I : BYTE;
  848. BEGIN
  849.   IF NOT (C IN [#07,#08,#10,#13]) THEN BEGIN
  850.     IF DoorSys.UseVirtScr THEN BEGIN
  851.       VirtScr^[VirtY-1,(VirtX-1)*2]   := BYTE(C);
  852.       VirtScr^[VirtY-1,(VirtX-1)*2+1] := TextAttr;
  853.     END;
  854.     INC(VirtX);
  855.   END ELSE CASE C OF
  856.    {#07 : Cursor does not move.}
  857.     #08 : IF VirtX > 1 THEN DEC(VirtX);
  858.     #10 : INC(VirtY);
  859.     #13 : VirtX := 1;
  860.   END;
  861.   IF (VirtX > 80) OR (VirtY > 25) OR (Yinc > 0) THEN BEGIN
  862.     IF (VirtX > 80) THEN VirtX := 1;
  863.     IF VirtY < 25 THEN INC(VirtY) ELSE BEGIN
  864.       VirtY := 25;
  865.       IF DoorSys.UseVirtScr THEN BEGIN
  866.         MOVE(VirtScr^[1],VirtScr^[0],4000-160);
  867.         FillWord(VirtScr^[24],160,TextAttr,' ');
  868.       END;
  869.     END;
  870.   END;
  871.   IF (DoorSys.UpdateLocal) THEN IF (VirtY <= DoorSys.LocalMaxY) THEN ShowCursor ELSE HideCursor;
  872. END;
  873. {───────────────────────────────────────────────────────────────────────────}
  874. PROCEDURE sWriteC;
  875. BEGIN
  876.   IF Carrier THEN BEGIN
  877.     IF DoorSys.Comport > 0 THEN BEGIN
  878.       CASE DoorSys.WhichIO OF
  879.         InternalIO : ComWriteChW(DoorSys.Comport,C);
  880.         FossilIO   : F_SendChar(DoorSys.Comport,C);
  881.       END;
  882.     END;
  883.   END ELSE DoorSys.Online := FALSE;
  884.   IF (DoorSys.UpdateLocal) THEN WRITE(C);
  885.   DoVirt(C,0);
  886. END;
  887. {───────────────────────────────────────────────────────────────────────────}
  888. PROCEDURE sWritelnC;
  889. BEGIN
  890.   IF Carrier THEN BEGIN
  891.     IF DoorSys.Comport > 0 THEN BEGIN
  892.       CASE DoorSys.WhichIO OF
  893.         InternalIO : I_ComWriteln(DoorSys.Comport,C);
  894.         FossilIO   : F_Writeln(DoorSys.Comport,C);
  895.       END;
  896.     END;
  897.   END ELSE DoorSys.Online := FALSE;
  898.   IF (DoorSys.UpdateLocal) AND NOT ((VirtY >= DoorSys.LocalMaxY) AND (C = #10)) AND (VirtY = WhereY) THEN WRITELN(C);
  899.   DoVirt(C,1);
  900. END;
  901. {───────────────────────────────────────────────────────────────────────────}
  902. PROCEDURE sWriteN;
  903. VAR
  904.   I : INTEGER;
  905.   S : STRING[12];
  906. BEGIN
  907.   STR(N,S);
  908.   FOR I := 1 TO LENGTH(S) DO sWriteC(S[I]);
  909. END;
  910. {───────────────────────────────────────────────────────────────────────────}
  911. PROCEDURE sWritelnN;
  912. VAR
  913.   I : INTEGER;
  914.   S : STRING[12];
  915. BEGIN
  916.   STR(N,S);
  917.   FOR I := 1 TO LENGTH(S)-1 DO sWriteC(S[I]);
  918.   sWritelnC(S[I+1]);
  919. END;
  920. {───────────────────────────────────────────────────────────────────────────}
  921. PROCEDURE sWrite;
  922. VAR
  923.   I : INTEGER;
  924. BEGIN
  925.   IF LENGTH(S) = 1 THEN sWriteC(S[1]) ELSE FOR I := 1 TO LENGTH(S) DO sWriteC(S[I]);
  926. END;
  927. {───────────────────────────────────────────────────────────────────────────}
  928. PROCEDURE sWriteln;
  929. VAR
  930.   I : INTEGER;
  931. BEGIN
  932.   IF S = '' THEN BEGIN
  933.     WRITELN(SIO,'');
  934.     EXIT;
  935.   END;
  936.   IF LENGTH(S) = 1 THEN BEGIN
  937.     sWritelnC(S[1]);
  938.     EXIT;
  939.   END;
  940.   FOR I := 1 TO LENGTH(S)-1 DO sWriteC(S[I]);
  941.   WRITELN(SIO,S[I+1]);
  942. END;
  943. {───────────────────────────────────────────────────────────────────────────}
  944. PROCEDURE sWaitInput(Ms : INTEGER);
  945. VAR
  946.   I : INTEGER;
  947. BEGIN
  948.   I := Ms DIV 10;
  949.   WHILE NOT ((I = 0) OR sKeyPressed) DO BEGIN
  950.     DELAY(10);
  951.     DEC(I);
  952.   END;
  953. END;
  954. {───────────────────────────────────────────────────────────────────────────}
  955. PROCEDURE CheckFKeys(Ch : CHAR);
  956. CONST
  957.   StatusType = 1 SHL 4 + 15;
  958.   Info       = 1 SHL 4 + 11;
  959. BEGIN
  960.   CASE Ch OF
  961.     F1 : WITH DoorSys DO IF UpdateStatusBar THEN BEGIN
  962.            UpdateStatusBar := FALSE;
  963.            DVWrite(1,StatusBarY,StatusType,'                                                                                ');
  964.            DVWrite(2,StatusBarY,StatusType,'F1:');   DVWrite(5,StatusBarY,Info,'Toggle');
  965.            DVWrite(12,StatusBarY,StatusType,'F2:');  DVWrite(15,StatusBarY,Info,'Shell');
  966.            DVWrite(21,StatusBarY,StatusType,'F3:');  DVWrite(24,StatusBarY,Info,'Chat');
  967.            DVWrite(29,StatusBarY,StatusType,'F4:');  DVWrite(32,StatusBarY,Info,'FakeVirus');
  968.            DVWrite(42,StatusBarY,StatusType,'F5:');  DVWrite(45,StatusBarY,Info,'-5 Min');
  969.            DVWrite(52,StatusBarY,StatusType,'F6:');  DVWrite(55,StatusBarY,Info,'+5 Min');
  970.            DVWrite(62,StatusBarY,StatusType,'F9:');  DVWrite(65,StatusBarY,Info,'Eject');
  971.            DVWrite(71,StatusBarY,StatusType,'F10:'); DVWrite(75,StatusBarY,Info,'Drop');
  972.            DVWrite(61,24,8,'Free Memory: '+IntToStr(MEMAVAIL));
  973.          END ELSE BEGIN
  974.            UpdateStatusBar := TRUE;
  975.            ShowStatusBar;
  976.            DVWrite(61,24,8,'Free Memory: '+IntToStr(MEMAVAIL));
  977.          END;
  978.     F2 : ShellToDos;
  979.     F3 : ChatSelect;
  980.     F4 : FakeVirus;
  981.     F5 : WITH DoorSys DO BEGIN
  982.            DEC(SecondsLeft,5 * 60);
  983.            IF SecondsLeft < 0 THEN SecondsLeft := 1;
  984.            MinutesLeft := SecondsLeft DIV 60;
  985.            DVWrite(2,StatusBarY-1,11,'Minutes Left:');
  986.            DVWrite(16,StatusBarY-1,15,PadRight(IntToStr(MinutesLeft),' ',4));
  987.          END;
  988.     F6 : WITH DoorSys DO BEGIN
  989.            INC(SecondsLeft,5 * 60);
  990.            IF SecondsLeft > (24 * 60 * 60) THEN SecondsLeft := (24 * 60 * 60);
  991.            MinutesLeft := SecondsLeft DIV 60;
  992.            DVWrite(2,StatusBarY-1,11,'Minutes Left:');
  993.            DVWrite(16,StatusBarY-1,15,PadRight(IntToStr(MinutesLeft),' ',4));
  994.          END;
  995.     F7 : WITH DoorSys DO IF UpdateStatusBar THEN BEGIN
  996.            UpdateStatusBar := FALSE;
  997.            HideStatusBar;
  998.          END ELSE BEGIN
  999.            UpdateStatusBar := TRUE;
  1000.            ShowStatusBar;
  1001.          END;
  1002.     F9 : HALT;
  1003.     F10: BEGIN
  1004.            IF NOT Local THEN _HangUp := TRUE;
  1005.            HALT;
  1006.          END;
  1007.   END;
  1008. END;
  1009. {───────────────────────────────────────────────────────────────────────────}
  1010. FUNCTION sReadkey;
  1011. VAR
  1012.   Ch        : CHAR;
  1013.   Found     : BOOLEAN;
  1014.   Cnt       : BYTE;
  1015.   LastCheck : BYTE;
  1016.   S100      : WORD;
  1017. BEGIN
  1018.   WITH CurTime DO GETTIME(Hour,Min,Sec,S100);
  1019.   LastCheck := CurTime.Sec;
  1020.   WITH DoorSys DO BEGIN
  1021.     IdleCount := 0;
  1022.     Cnt       := 0;
  1023.     Ch        := #0;
  1024.     Found     := FALSE;
  1025.     LocalKey  := FALSE;
  1026.     REPEAT
  1027.       WITH CurTime DO GETTIME(Hour,Min,Sec,S100);
  1028.       IF LastCheck <> CurTime.Sec THEN BEGIN
  1029.         UpdateTime;
  1030.         LastCheck := CurTime.Sec;
  1031.       END;
  1032.       IF (LocalInputON) AND (NOT Found) THEN BEGIN
  1033.         IF KEYPRESSED THEN BEGIN
  1034.           s_ReadKey := '';
  1035.           Ch := READKEY;
  1036.           s_ReadKey := s_ReadKey + Ch;
  1037.           Found := (Ch <> #0);
  1038.           IF Ch = #0 THEN BEGIN
  1039.             Ch := READKEY;
  1040.             s_ReadKey := s_ReadKey + Ch;
  1041.             IF Ch IN [F1..F10,AltF1..AltF10] THEN CheckFKeys(Ch)
  1042.             ELSE BEGIN
  1043.               Ch       := #0;
  1044.               Found    := TRUE;
  1045.               LocalKey := TRUE;
  1046.             END;
  1047.           END ELSE LocalKey := TRUE;
  1048.         END;
  1049.       END;
  1050.       IF (NOT Found) AND (Comport > 0) THEN BEGIN
  1051.         CASE WhichIO OF
  1052.           InternalIO : BEGIN
  1053.                          Found := ComBufferLeft(Comport,'I') > 0;
  1054.                          IF Found THEN Ch := ComReadCh(Comport);
  1055.                          LocalKey := NOT Found;
  1056.                        END;
  1057.           FossilIO   : BEGIN
  1058.                          Found := TRUE;
  1059.                          IF F_Avail(Comport) THEN Ch := F_ReadChar(Comport) ELSE Found := FALSE;
  1060.                          LocalKey := NOT Found;
  1061.                        END;
  1062.         END;
  1063.       END;
  1064.       IF Cnt >= 100 THEN BEGIN
  1065.         Cnt := 25;
  1066.         TimeSlice;
  1067.       END ELSE INC(Cnt);
  1068.     UNTIL Found;
  1069.     sReadKey := Ch;
  1070.   END;
  1071. END;
  1072. {───────────────────────────────────────────────────────────────────────────}
  1073. PROCEDURE SetFore;
  1074. BEGIN
  1075.   Set_Color(Fore,TextAttr SHR 4);
  1076. END;
  1077. {───────────────────────────────────────────────────────────────────────────}
  1078. PROCEDURE SetBack;
  1079. BEGIN
  1080.   Set_Color(TextAttr MOD 16, Back);
  1081. END;
  1082. {───────────────────────────────────────────────────────────────────────────}
  1083. PROCEDURE AddANSIcode(VAR St : STRING; StAdd : STRING);
  1084. BEGIN
  1085.   IF St[LENGTH(St)] <> '[' THEN St := St + ';' + StAdd
  1086.                            ELSE St := St + StAdd;
  1087. END;
  1088. {───────────────────────────────────────────────────────────────────────────}
  1089. FUNCTION AnsiColor : STRING;
  1090. VAR
  1091.   Temp : STRING;
  1092. CONST
  1093.   AnsiColors : ARRAY[0..7] OF CHAR = '04261537';
  1094. BEGIN
  1095.   Temp := '';
  1096.   IF CurColor <> TextAttr THEN BEGIN
  1097.     IF Graphics IN [Ansi,Rip] THEN BEGIN
  1098.       Temp := #27'[';
  1099.       IF TextAttr = LightGray THEN AddAnsiCode(Temp,'0') ELSE BEGIN
  1100.         IF (TextAttr AND $8) <> (CurColor AND $8) THEN
  1101.           IF (TextAttr AND $8 = $8) THEN AddAnsiCode(Temp,'1') ELSE BEGIN
  1102.             CurColor := Lightgray;
  1103.             Temp := #27'[0';
  1104.           END;
  1105.           IF (TextAttr AND $80) <> (CurColor AND $80) THEN
  1106.           IF (TextAttr AND $80 = $80) THEN AddAnsiCode(temp,'5') ELSE BEGIN
  1107.             CurColor := LightGray;
  1108.             Temp := #27'[0';
  1109.             IF (TextAttr AND $8 = $8) THEN AddAnsiCode(Temp,'1')
  1110.           END;
  1111.         IF (TextAttr AND $7) <> (CurColor AND $7) THEN
  1112.             AddAnsiCode(Temp,'3' + AnsiColors[TextAttr AND $7]);
  1113.         IF (TextAttr SHR $4) <> (CurColor SHR $4) THEN
  1114.             AddAnsiCode(Temp,'4' + AnsiColors[(TextAttr SHR $4) AND $7]);
  1115.       END;
  1116.       Temp := Temp + 'm';
  1117.     END ELSE IF Graphics = Avatar THEN BEGIN
  1118.       Temp := #22#1 + CHAR(TextAttr AND $7F);
  1119.       IF (TextAttr AND $80 = $80) THEN Temp := Temp + #22#2;
  1120.     END;
  1121.   END;
  1122.   AnsiColor := Temp;
  1123. END;
  1124. {───────────────────────────────────────────────────────────────────────────}
  1125. PROCEDURE Set_Color(Fore,Back : BYTE);
  1126. BEGIN
  1127.   TextColor(Fore);
  1128.   TextBackground(Back);
  1129.   IF (NOT Local) AND (CurColor <> TextAttr) Then SendStr(AnsiColor);
  1130.   CurColor := TextAttr;
  1131. END;
  1132. {───────────────────────────────────────────────────────────────────────────}
  1133. PROCEDURE ShowStatusBar;
  1134. CONST
  1135.   StatusType = 1 SHL 4 + 15;
  1136.   Info       = 1 SHL 4 + 11;
  1137.   SysopInfo  = 1 SHL 4 + 14;
  1138. VAR
  1139.   X,Y : BYTE;
  1140. BEGIN
  1141.   DoorSys.UpdateStatusBar := TRUE;
  1142.   DoorSys.LocalMaxY       := DoorSys.StatusBarY-1;
  1143.   X                       := VirtX;
  1144.   Y                       := VirtY;
  1145.   WINDOW(1,1,80,DoorSys.StatusBarY-1);
  1146.   GOTOXY(X,Y);
  1147.   IF (Y > DoorSys.LocalMaxY) THEN HideCursor;
  1148.   WITH DoorSys DO BEGIN
  1149.     DVWrite(1,StatusBarY,StatusType,'                                                                                ');
  1150.     DVWrite(2,StatusBarY,StatusType,'User:');  DVWrite(8,StatusBarY,Info,UserName);
  1151.     DVWrite(28,StatusBarY,StatusType,'BPS:');  DVWrite(33,StatusBarY,Info,IntToStr(BaudRate));
  1152.     DVWrite(39,StatusBarY,StatusType,'Node:'); DVWrite(45,StatusBarY,Info,IntToStr(Node));
  1153.     DVWrite(49,StatusBarY,StatusType,'Sec:');  DVWrite(54,StatusBarY,Info,IntToStr(Access));
  1154.     DVWrite(60,StatusBarY,StatusType,'Port:'); DVWrite(66,StatusBarY,Info,IntToStr(ComPort));
  1155.     DVWrite(69,StatusBarY,SysopInfo,'(F1 : Help)');
  1156.   END;
  1157. END;
  1158. {───────────────────────────────────────────────────────────────────────────}
  1159. PROCEDURE HideStatusBar;
  1160. VAR
  1161.   X,Y,A : BYTE;
  1162. BEGIN
  1163.   DoorSys.UpdateStatusBar := FALSE;
  1164.   DoorSys.LocalMaxY       := DoorSys.StatusBarY;
  1165.   X                       := VirtX;
  1166.   Y                       := VirtY;
  1167.   WINDOW(1,1,80,DoorSys.StatusBarY);
  1168.   GOTOXY(1,DoorSys.StatusBarY);
  1169.   A        := TextAttr;
  1170.   TextAttr := 7;
  1171.   CLREOL;
  1172.   TextAttr := A;
  1173.   GOTOXY(X,Y);
  1174.   ShowCursor;
  1175. END;
  1176. {───────────────────────────────────────────────────────────────────────────}
  1177. PROCEDURE Wait;
  1178. VAR
  1179.   U,Chs,Shs,CurSec,StartSec : WORD;
  1180. BEGIN
  1181.   GETTIME(U,U,StartSec,Shs);
  1182.   WHILE Seconds > 0 DO BEGIN
  1183.     REPEAT
  1184.       GETTIME(U,U,CurSec,Chs);
  1185.       TimeSlice;
  1186.       TimeSlice;
  1187.     UNTIL (CurSec <> StartSec);
  1188.     StartSec := CurSec;
  1189.     DEC(Seconds);
  1190.   END;
  1191. END;
  1192. {───────────────────────────────────────────────────────────────────────────}
  1193. FUNCTION InitVirtScr : BOOLEAN;
  1194. BEGIN
  1195.   InitVirtScr := FALSE;
  1196.   IF NOT DoorSys.UseVirtScr THEN BEGIN
  1197.     IF (VirtScr = NIL) AND (MAXAVAIL > SIZEOF(VirtScr^)) THEN BEGIN
  1198.       GETMEM(VirtScr,SIZEOF(VirtScr^));
  1199.       FillWord(VirtScr^,SIZEOF(VirtScr^),7,' ');
  1200.       VirtX              := 1;
  1201.       VirtY              := 1;
  1202.       DoorSys.UseVirtScr := TRUE;
  1203.     END ELSE DoorSys.UseVirtScr := FALSE;
  1204.     InitVirtScr := DoorSys.UseVirtScr;
  1205.   END;
  1206. END;
  1207. {───────────────────────────────────────────────────────────────────────────}
  1208. PROCEDURE FreeVirtScr;
  1209. BEGIN
  1210.   IF VirtScr <> NIL THEN FREEMEM(VirtScr,SIZEOF(VirtScr^));
  1211.   VirtScr            := NIL;
  1212.   DoorSys.UseVirtScr := FALSE;
  1213. END;
  1214. {───────────────────────────────────────────────────────────────────────────}
  1215. PROCEDURE DrawScr(Scr : POINTER; X1,Y1,X2,Y2 : BYTE);
  1216. VAR
  1217.   X,Y,VX,VY : BYTE;
  1218. BEGIN
  1219.   VX := VirtX;
  1220.   VY := VirtY;
  1221.   IF scr = NIL THEN BEGIN
  1222.     sClrScr;
  1223.   END ELSE BEGIN
  1224.     FOR Y := Y1-1 TO Y2-1 DO BEGIN
  1225.       sGotoXY(X1,Y+1);
  1226.       FOR X := X1-1 TO X2-1 DO IF (Y <> 25-1) OR (X <> 80-1) THEN BEGIN
  1227.         TextAttr := tScreen(Scr^)[Y,(X*2)+1];
  1228.         sWriteC(CHAR(tScreen(Scr^)[Y,(X*2)]));
  1229.       END;
  1230.     END;
  1231.     sGotoXY(VX,VY);
  1232.   END;
  1233. END;
  1234. { ────────────────────────────────────────────────────────────────────────── }
  1235. PROCEDURE Autodetect;
  1236. VAR
  1237.   RipG,
  1238.   MaxG,
  1239.   AnsiG,
  1240.   AvatarG : BOOLEAN;
  1241.   Loop    : BYTE;
  1242.   Ch      : CHAR;
  1243.   Temp    : STRING;
  1244.   Code    : INTEGER;
  1245. BEGIN
  1246.   RipG     := FALSE;
  1247.   MaxG     := FALSE;
  1248.   AvatarG  := FALSE;
  1249.   AnsiG    := FALSE;
  1250.   Graphics := Ansi;
  1251.   MaxID    := '';
  1252.   {Detect RIP Graphics}
  1253.   sClrScr;
  1254.   OutTxt(5,0,'■ Detecting RIP Graphics.......');
  1255.   Set_Color(0,0);
  1256.   IF NOT Local THEN BEGIN
  1257.     PurgeInput;
  1258.     SendStr(AnsiColor+#27'[!');
  1259.     Loop     := 1;
  1260.     REPEAT
  1261.       DELAY(10);
  1262.       INC(Loop);
  1263.     UNTIL (Loop = 50) OR DataAvailable;
  1264.     IF NOT Local THEN IF DataAvailable THEN RipG := TRUE;
  1265.   END;
  1266.   {Detect MAX Graphics}
  1267.   IF RipG THEN BEGIN
  1268.     sWriteln('');
  1269.     OutTxt(5,0,'■ Detecting MAX Graphics.......');
  1270.     Set_Color(0,0);
  1271.     PurgeInput;
  1272.     SendStr(#255'~'#255);
  1273.     Loop     := 1;
  1274.     REPEAT
  1275.       DELAY(10);
  1276.       INC(Loop);
  1277.     UNTIL (Loop = 150) OR DataAvailable;
  1278.     IF DataAvailable THEN BEGIN
  1279.       MaxG := TRUE;
  1280.       RipG := FALSE;
  1281.       WHILE DataAvailable DO BEGIN
  1282.         Ch    := sReadKey;
  1283.         MaxID := MaxID + Ch;
  1284.       END;
  1285.     END;
  1286.   END;
  1287.   sWriteln('');
  1288.   {Detect Ansi/Avatar Graphics}
  1289.   OutTxt(5,0,'■ Detecting ANSI Graphics......');
  1290.   Set_Color(0,0);
  1291.   IF NOT Local THEN BEGIN
  1292.     PurgeInput;
  1293.     SendStr(AnsiColor+#22#8#2#70#27'[6n');
  1294.     Loop     := 1;
  1295.     REPEAT
  1296.       DELAY(10);
  1297.       INC(loop);
  1298.     UNTIL (Loop = 150) OR DataAvailable;
  1299.     DELAY(50);
  1300.     WHILE DataAvailable DO BEGIN
  1301.       Ch := sReadKey;
  1302.       IF Ch = '7' THEN AvatarG := TRUE;
  1303.       IF Ch = '[' THEN AnsiG   := TRUE;
  1304.     END;
  1305.   END;
  1306.   sWriteln('');
  1307.   IF RipG THEN Graphics := Rip ELSE
  1308.   IF MaxG THEN Graphics := Max ELSE
  1309.   IF AvatarG THEN Graphics := Avatar ELSE
  1310.   IF AnsiG THEN Graphics := Ansi ELSE BEGIN
  1311.     Graphics := Tty;
  1312.     IF NOT Local THEN OutTxtL(4,0,'■ No Graphics Detected.........') ELSE Graphics := Ansi;
  1313.   END;
  1314.   IF (Graphics <> TTY) AND (Graphics <> MAX) THEN BEGIN
  1315.     OutTxt(1,0,'■ Detecting Screen Length......');
  1316.     Set_Color(0,0);
  1317.     sCursorDown(25);
  1318.     IF NOT Local THEN BEGIN
  1319.       PurgeInput;
  1320.       Temp := '';
  1321.       SendStr(#27'[6n');
  1322.       Loop := 1;
  1323.       REPEAT
  1324.         DELAY(10);
  1325.         INC(loop);
  1326.       UNTIL (Loop = 150) OR DataAvailable;
  1327.       DELAY(50);
  1328.       WHILE DataAvailable DO BEGIN
  1329.         Ch   := sReadKey;
  1330.         Temp := Temp + Ch;
  1331.       END;
  1332.       VAL(COPY(Temp,3,POS(';',Temp)-3),LengthScr,Code);
  1333.       IF Code <> 0 THEN LengthScr := 24;
  1334.     END ELSE Lengthscr := HI(WindMax);
  1335.     sGotoXY(1,4);
  1336.     OutTxtL(1,0,'■ Screen Length Set To '+IntToStr(LengthScr)+' Rows.');
  1337.   END;
  1338.   IF Local THEN OutTxtL(9,0,'■ Local Mode Now Active........')
  1339.   ELSE CASE Graphics OF
  1340.     Rip    : OutTxtL(9,0,'■ RIP Graphics Detected........');
  1341.     Max    : OutTxtL(9,0,'■ MAX Graphics Detected........');
  1342.     Avatar : OutTxtL(9,0,'■ AVATAR Graphics Detected.....');
  1343.     Ansi   : OutTxtL(9,0,'■ ANSI Graphics Detected.......');
  1344.   END;
  1345.   Log('Screen Length Set To '+IntToStr(LengthScr)+' Rows');
  1346.   sWriteln('');
  1347.   Set_Color(11,0);
  1348.   {Detect Local Operating System}
  1349.   SystemEnv := NoTasker;
  1350.   DetectOS;
  1351.   CASE SystemEnv OF
  1352.     NoTasker  : sWriteln('■ No Multi-Tasker Detected.');
  1353.     DDOS      : sWriteln('■ Double-Dos Detected.');
  1354.     DV        : sWriteln('■ DesqView Detected.');
  1355.     WIN       : sWriteln('■ MS Windows Detected.');
  1356.     OS2       : sWriteln('■ IBM OS/2 Detected.');
  1357.     Network   : sWriteln('■ Network Detected.');
  1358.   END;
  1359.   IF NOT Local THEN BEGIN
  1360.     IF DoorSys.WhichIO = FossilIO THEN OutTxt(3,0,'■ Using Fossil Comm Routines.')
  1361.                                   ELSE OutTxt(3,0,'■ Using Internal Comm Routines.');
  1362.   END;
  1363.   Wait(1);
  1364.   TextAttr := 7;
  1365. END;
  1366. { ────────────────────────────────────────────────────────────────────────── }
  1367. PROCEDURE ShutDownDoor; Far;
  1368. VAR
  1369.   Loop    : BYTE;
  1370.   E,OsStr : STRING[40];
  1371. BEGIN
  1372.   RipToText;
  1373.   HideStatusBar;
  1374.   NORMVIDEO;
  1375.   FreeVirtScr;
  1376.   TEXTBACKGROUND(0); CLRSCR;
  1377.   IF KillDrop THEN BEGIN
  1378.     FErase(DropFilePath+'DOOR.SYS');
  1379.     FErase(DropFilePath+'DORINFO'+IntToStr(DoorSys.Node)+'.DEF');
  1380.   END;
  1381.   IF (Local) AND (ErrLevel = 3) THEN ErrLevel := 0;
  1382.   CASE ErrLevel OF
  1383.     0 : E := 'Normal Exit';
  1384.     1 : E := 'Comm Port Error';
  1385.     2 : E := 'Unable To Open Drop File';
  1386.     3 : E := 'Carrier Lost';
  1387.     4 : E := 'User Time Limit Expired';
  1388.     5 : E := 'User Fell Asleep At The Keyboard';
  1389.     6 : E := 'CRITICAL ERROR! - System File Missing';
  1390.   END;
  1391.   IF ErrLevel > 6 THEN E := 'SysOp Defined Exit';
  1392.   IF (UseLog) And (LogFile <> '') THEN BEGIN
  1393.     Log(E);
  1394.     Log('Exiting At ErrorLevel '+IntToStr(ErrLevel));
  1395.     Log('END');
  1396.   END;
  1397.   IF NOT HideParams THEN BEGIN
  1398.     TEXTCOLOR(3);
  1399.     DetectOS;
  1400.     CASE SystemEnv OF
  1401.       NoTasker  : OsStr := 'DOS / No Multi-Tasker';
  1402.       DDOS      : OsStr := 'Double-Dos';
  1403.       DV        : OsStr := 'DesqView';
  1404.       WIN       : OsStr := 'MS Windows';
  1405.       OS2       : OsStr := 'IBM OS/2';
  1406.       Network   : OsStr := 'Network';
  1407.     END;
  1408.     WRITELN;
  1409.     WRITELN('    Program Name: ' + ProgramName);
  1410.     WRITE(' Parameters Used: (');
  1411.     FOR Loop := 1 TO PARAMCOUNT DO WRITE(AllCaps(PARAMSTR(Loop))+' ');
  1412.     WRITELN(')');
  1413.     WRITELN('Operating System: '+OsStr);
  1414.     WRITELN('  Available Heap: '+IntToStr(MEMAVAIL));
  1415.     WRITELN('     Error Level: '+IntToStr(ErrLevel));
  1416.     WRITELN('       Exit Type: '+E);
  1417.     TEXTCOLOR(7);
  1418.     WRITELN; WRITELN;
  1419.    IF ((NOT Carrier) AND (NOT Local)) OR (ErrLevel = 3) THEN HALT(3);
  1420.   END;
  1421.   IF (ErrLevel = 4) OR (ErrLevel = 5) OR (_HangUp) THEN Lower_DTR;
  1422.   IF ((NOT Carrier) AND (NOT Local)) OR (ErrLevel = 3) THEN HALT(3);
  1423.   FlushOutput;
  1424.   DeInitComport;
  1425.   Halt(ErrLevel);
  1426. END;
  1427. {───────────────────────────────────────────────────────────────────────────}
  1428. PROCEDURE FakeVirus;
  1429. VAR
  1430.   ProgCh : CHAR;
  1431.   Col,
  1432.   CPS,B,
  1433.   Loop,L : WORD;
  1434. BEGIN
  1435.   OutTxtXYL(11,5,15,1,'╒═╡ Zmodem Download ╞════════════════════════════════════╕');
  1436.   OutTxtXYL(11,6,15,1,'│                                                        │');
  1437.   OutTxtXYL(11,7,15,1,'│ File name :                                            │');
  1438.   OutTxtXYL(11,8,15,1,'│ File path :                                            │');
  1439.   OutTxtXY(11,9,15,1,'│');OutTxt(14,1,' ──────────────────────────────────────────────────────');OutTxtL(15,1,' │');
  1440.   OutTxtXY(11,10,15,1,'│');OutTxt(14,1,' Baud Rate      :           Approx CPS rate :          ');OutTxtL(15,1,' │');
  1441.   OutTxtXY(11,11,15,1,'│');OutTxt(14,1,' Transfer time  :           Bytes to send   :          ');OutTxtL(15,1,' │');
  1442.   OutTxtXY(11,12,15,1,'│');OutTxt(14,1,' Time remaining :           Bytes sent      :          ');OutTxtL(15,1,' │');
  1443.   OutTxtXY(11,13,15,1,'│');OutTxt(14,1,' ──────────────────────────────────────────────────────');OutTxtL(15,1,' │');
  1444.   OutTxtXYL(11,14,15,1,'│ ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░ Progress Ind. │');
  1445.   OutTxtXY(11,15,15,1,'│');OutTxt(14,1,' ──────────────────────────────────────────────────────');OutTxtL(15,1,' │');
  1446.   OutTxtXYL(11,16,15,1,'│ Last status/error : None                               │');
  1447.   OutTxtXYL(11,17,15,1,'╘════════════════════════════════════════════════════════╛');
  1448.   ProgCh := '█'; L := 0; B := 0; Col := 13;
  1449.   IF Local THEN DoorSys.BaudRate := 14400;
  1450.   CPS := DoorSys.BaudRate DIV 9;
  1451.   OutTxtXY(30,10,14,1,IntToStr(DoorSys.BaudRate));
  1452.   OutTxtXY(25,7,15,1,'VIRUS.COM');
  1453.   OutTxtXY(25,8,15,1,'C:\');
  1454.   OutTxtXY(30,11,14,1,'00:15');
  1455.   OutTxtXY(30,12,14,1,'00:14');
  1456.   OutTxtXY(58,10,14,1,IntToStr(CPS));
  1457.   OutTxtXY(58,11,14,1,'4000');
  1458.   FOR Loop := 1 TO 4000 DO BEGIN
  1459.     INC(L); INC(B);
  1460.     IF L = 100 THEN BEGIN
  1461.       L := 0;
  1462.       OutTxtXY(Col,14,15,1,ProgCh);
  1463.       OutTxtXY(58,12,14,1,IntToStr(B));
  1464.       DELAY(30);
  1465.       INC(Col);
  1466.     END;
  1467.   END;
  1468.   OutTxtXY(30,12,14,1,'00:00');
  1469.   OutTxtXY(33,16,10,1,'Download Complete!');
  1470.   AlertTones;
  1471.   DELAY(2000);
  1472.   Set_Color(7,0);
  1473.   IF NOT Local THEN _HangUp := True;
  1474.   HALT;
  1475. END;
  1476. {───────────────────────────────────────────────────────────────────────────}
  1477. PROCEDURE SplitUserName;
  1478. VAR
  1479.   Loop  : BYTE;
  1480.   FDone,
  1481.   LDone : BOOLEAN;
  1482. BEGIN
  1483.   UFirst := ''; ULast := ''; FDone := FALSE; LDone := TRUE;
  1484.   FOR Loop := 1 TO LENGTH(DoorSys.UserName) DO BEGIN
  1485.     IF DoorSys.UserName[Loop - 1] = ' ' THEN BEGIN
  1486.       FDone := TRUE;
  1487.       LDone := FALSE;
  1488.     END;
  1489.     IF (NOT FDone) AND (DoorSys.UserName[Loop] <> ' ') THEN UFirst := UFirst + DoorSys.UserName[Loop];
  1490.     IF NOT LDone THEN ULast := ULast + DoorSys.UserName[Loop];
  1491.   END;
  1492. END;
  1493. {───────────────────────────────────────────────────────────────────────────}
  1494. PROCEDURE ReadDorInfo(DoorFn : PathStr; VAR DropInfo : tDoor);
  1495. VAR
  1496.   DoorDrop : Text;
  1497.   Temp     : STRING;
  1498.   Code     : INTEGER;
  1499.   Temp2    : STRING;
  1500.   Loop     : BYTE;
  1501. BEGIN
  1502.   IF (DoorFn <> '') THEN BEGIN
  1503.     ASSIGN(DoorDrop,DoorFn);
  1504.     RESET(DoorDrop);
  1505.   END;
  1506.   IF (IORESULT <> 0) OR (DoorFn = '') THEN BEGIN
  1507.     TextAttr := 12;
  1508.     WRITELN('Unable To Open '+DoorFn+'!');
  1509.     ErrLevel := 2;
  1510.     ErrorLog('Unable To Open '+DoorFn+'!',ErrLevel,TRUE);
  1511.   END;
  1512.   WITH DropInfo DO BEGIN
  1513.     Node := BYTE(DoorFn[BYTE(DoorFn[0]) - LENGTH('.DEF')]) - 48;
  1514.     READLN(DoorDrop,BBSname);
  1515.     READLN(DoorDrop,Temp);
  1516.     READLN(DoorDrop,Temp2);
  1517.     READLN(DoorDrop,Temp);
  1518.     VAL(COPY(Temp,4,255),Comport,Code);
  1519.     Local := Comport = 0;
  1520.     READLN(DoorDrop,Temp);
  1521.     Loop := 1;
  1522.     WHILE Temp[Loop] <> #32 DO INC(Loop);
  1523.     Temp[0] := CHAR(loop - 1);
  1524.     VAL(Temp,BaudRate,Code);
  1525.     READLN(DoorDrop,Temp);
  1526.     READLN(DoorDrop,Temp);
  1527.     READLN(DoorDrop,Temp2);
  1528.     IF Temp2 <> 'NLN' THEN UserName := Temp+' '+Temp2 ELSE UserName := Temp;
  1529.     READLN(DoorDrop,UserCity);
  1530.     READLN(DoorDrop,Graphics);
  1531.     READLN(DoorDrop,Access);
  1532.     READLN(DoorDrop,MinutesLeft);
  1533.     SecondsLeft := MinutesLeft * LONGINT(60);
  1534.     CLOSE(DoorDrop);
  1535.     Phone     := '123-456-7890';
  1536.     WorkPhone := Phone;
  1537.     Password  := 'PASSWORD';
  1538.     Alias     := UserName;
  1539.   END;
  1540.   SplitUserName;
  1541. END;
  1542. { ────────────────────────────────────────────────────────────────────────── }
  1543. PROCEDURE ReadDoorSys(DoorFn : PathStr; VAR DropInfo : tDoor);
  1544. VAR
  1545.   DoorDrop  : Text;
  1546.   Temp      : STRING;
  1547.   Loop,Code : INTEGER;
  1548. BEGIN
  1549.   IF (DoorFn <> '') THEN BEGIN
  1550.     ASSIGN(DoorDrop,DoorFn);
  1551.     RESET(DoorDrop);
  1552.   END;
  1553.   IF (IORESULT <> 0) OR (DoorFn = '') THEN BEGIN
  1554.     TextAttr := 12;
  1555.     WRITELN('Unable To Open '+DoorFn+'!');
  1556.     ErrLevel := 2;
  1557.     ErrorLog('Unable To Open '+DoorFn+'!',ErrLevel,TRUE);
  1558.   END;
  1559.   WITH DropInfo DO BEGIN
  1560.     BBSname := 'The BBS';
  1561.     READLN(DoorDrop,Temp);
  1562.     VAL(COPY(Temp,4,LENGTH(Temp) - 4),Comport,Code);
  1563.     Local := Comport = 0;
  1564.     READLN(DoorDrop,Temp);
  1565.     VAL(Temp,BaudRate,Loop);
  1566.     READLN(DoorDrop,Temp);
  1567.     READLN(DoorDrop,Node);
  1568.     READLN(DoorDrop,Temp);
  1569.     IF UPCASE(Temp[1]) <> 'N' THEN VAL(Temp,BaudRate,Loop);
  1570.     FOR Loop := 1 TO 4 DO READLN(DoorDrop,Temp);
  1571.     READLN(DoorDrop,UserName);
  1572.     READLN(DoorDrop,UserCity);
  1573.     READLN(DoorDrop,Phone);
  1574.     READLN(DoorDrop,WorkPhone);
  1575.     READLN(DoorDrop,Password);
  1576.     READLN(DoorDrop,Access);
  1577.     FOR Loop := 1 TO 3 DO READLN(DoorDrop,Temp);
  1578.     READLN(DoorDrop,MinutesLeft);
  1579.     SecondsLeft := Minutesleft * LONGINT(60);
  1580.     Loop := 0;
  1581.     CLOSE(DoorDrop);
  1582.     RESET(DoorDrop);
  1583.     WHILE NOT EOF(DoorDrop) DO BEGIN
  1584.       INC(Loop);
  1585.       READLN(DoorDrop,Temp);
  1586.       IF Loop = 36 THEN Alias := Temp;
  1587.     END;
  1588.     IF Loop < 36 THEN Alias := UserName;
  1589.   END;
  1590.   CLOSE(DoorDrop);
  1591.   SplitUserName;
  1592. END;
  1593. {───────────────────────────────────────────────────────────────────────────}
  1594. PROCEDURE SaveScreen;
  1595. BEGIN
  1596.   MOVE(Mem[$B800:0000],Buffer,4000);
  1597. END;
  1598. {───────────────────────────────────────────────────────────────────────────}
  1599. PROCEDURE RestoreScreen;
  1600. BEGIN
  1601.   MOVE(Buffer,Mem[$B800:0000],4000);
  1602. END;
  1603. {───────────────────────────────────────────────────────────────────────────}
  1604. PROCEDURE ShellToDos;
  1605. VAR
  1606.   TheDir : STRING;
  1607. BEGIN
  1608.   sWriteln(''); sWriteln('');
  1609.   OutTxt(12,0,'The SysOp Has Shelled To DOS, Please Wait....');
  1610.   GETDIR(0,TheDir);
  1611.   CLRSCR;
  1612.   PutEnv('PROMPT=Type: EXIT and press <ENTER> to return to '+ProgramName+'!$_$p$g');
  1613.   Do_Exec(GetEnv('COMSPEC'),' /C ' + GetEnv('COMSPEC'),Use_All,$ffff,TRUE);
  1614.   ShowStatusBar;
  1615.   CHDIR(TheDir);
  1616.   sClrScr;
  1617.   OutTxtL(10,0,'The SysOp Has Returned From DOS....');
  1618.   sWriteln('');
  1619.   AnyKey;
  1620. END;
  1621. {───────────────────────────────────────────────────────────────────────────}
  1622. FUNCTION LocateFile(FName : STRING) : STRING;
  1623. VAR
  1624.   F : STRING;
  1625. BEGIN
  1626.   IF NOT FExist(FName) THEN BEGIN
  1627.     F := FSearch(FName,GetEnv('PATH'));
  1628.     LocateFile := FExpand(F);
  1629.     EXIT;
  1630.   END ELSE LocateFile := FName;
  1631. END;
  1632. {───────────────────────────────────────────────────────────────────────────}
  1633. PROCEDURE _Execute(FName,Params : STRING);
  1634. VAR
  1635.   TheDir : STRING;
  1636. BEGIN
  1637.   FName := LocateFile(FName);
  1638.   IF FName = '' THEN EXIT;
  1639.   GETDIR(0,TheDir);
  1640.   Do_Exec(FName,Params,Use_All,$ffff,TRUE);
  1641.   CHDIR(TheDir);
  1642.   DoorSys.IdleCount := 0;
  1643.   UpdateTime;
  1644. END;
  1645. {───────────────────────────────────────────────────────────────────────────}
  1646. PROCEDURE Execute(FName,Params : STRING);
  1647. VAR
  1648.   TheDir : STRING;
  1649. BEGIN
  1650.   FName := LocateFile(FName);
  1651.   IF FName = '' THEN EXIT;
  1652.   GETDIR(0,TheDir);
  1653.   SaveScreen;
  1654.   Do_Exec(FName,Params,Use_All,$ffff,TRUE);
  1655.   RestoreScreen;
  1656.   ShowStatusBar;
  1657.   CHDIR(TheDir);
  1658.   DoorSys.IdleCount := 0;
  1659.   UpdateTime;
  1660. END;
  1661. {───────────────────────────────────────────────────────────────────────────}
  1662. PROCEDURE RunBatFile(TheBat : STRING);
  1663. VAR
  1664.   TheDir : STRING;
  1665. BEGIN
  1666.   GETDIR(0,TheDir);
  1667.   SaveScreen;
  1668.   Do_Exec(GetEnv('COMSPEC'),' /C ' + TheBat,Use_All,$ffff,TRUE);
  1669.   RestoreScreen;
  1670.   ShowStatusBar;
  1671.   CHDIR(TheDir);
  1672.   DoorSys.IdleCount := 0;
  1673.   UpdateTime;
  1674. END;
  1675. {───────────────────────────────────────────────────────────────────────────}
  1676. PROCEDURE CommandLineHelp;
  1677. BEGIN
  1678.   ShowProgramAd;
  1679.   WRITELN;
  1680.   TextAttr := 10;
  1681.   WRITELN('Command Line Parameters');
  1682.   LineBar(2,0,23);
  1683.   TextAttr := 3;
  1684.   IF UseDoorSys THEN WRITELN(PARAMSTR(0) + ' /D={Node Work Path}\DOOR.SYS');
  1685.   IF UseDorInfo THEN WRITELN(PARAMSTR(0) + ' /R={Node Work Path}\DORINFO#.DEF');
  1686.   WRITELN;
  1687.   WRITELN('Add /N### To Force Node Number');
  1688.   WRITELN('Add /S##### To Force Baud Rate');
  1689.   WRITELN;
  1690.   IF IntConfig THEN WRITELN('Use /CONFIG To Configure');
  1691.   IF UseLocal  THEN WRITELN('Use /L To Force Local Mode');
  1692.   TextAttr := 7;
  1693.   sGOTOXY(1,24);
  1694.   AnyKey;
  1695.   Halt(ErrLevel);
  1696. END;
  1697. {───────────────────────────────────────────────────────────────────────────}
  1698. PROCEDURE DoCommandLine;
  1699. VAR
  1700.   ExtParams : BOOLEAN;
  1701.   TempParam : STRING;
  1702.   NewBaud   : LONGINT;
  1703.   NewNode,
  1704.   Code      : INTEGER;
  1705.   Loop      : BYTE;
  1706. BEGIN
  1707.   NewNode := - 1;
  1708.   NewBaud := 0;
  1709.   Local   := False;
  1710.   IF PARAMCOUNT = 0 THEN CommandLineHelp;
  1711.   FOR Loop := 1 TO PARAMCOUNT DO BEGIN
  1712.     TempParam := AllCaps(PARAMSTR(Loop));
  1713.     IF TempParam[1] = '/' THEN BEGIN
  1714.       CASE TempParam[2] OF
  1715.         'D' : BEGIN
  1716.                 ReadDoorSys(COPY(TempParam,4,255),DoorSys);
  1717.                 DropFilePath := GetFilePath(COPY(TempParam,4,255));
  1718.               END;
  1719.         'R' : BEGIN
  1720.                 ReadDorinfo(COPY(TempParam,4,255),DoorSys);
  1721.                 DropFilePath := GetFilePath(COPY(TempParam,4,255));
  1722.               END;
  1723.         'N' : BEGIN
  1724.                 VAL(COPY(TempParam,3,255),NewNode,Code);
  1725.                 IF Code <> 0 THEN BEGIN
  1726.                   WRITELN('Error In Forced Node Number: '+TempParam);
  1727.                   AlertTones;
  1728.                   ErrLevel := 1;
  1729.                   ErrorLog('Error In Forced Node Number: '+TempParam,ErrLevel,TRUE);
  1730.                 END;
  1731.               END;
  1732.         'S' : BEGIN
  1733.                 VAL(COPY(TempParam,3,255),NewBaud,Code);
  1734.                 IF Code <> 0 THEN BEGIN
  1735.                   WRITELN('Error In Forced Baud Rate: '+TempParam);
  1736.                   AlertTones;
  1737.                   ErrLevel := 1;
  1738.                   ErrorLog('Error In Forced Baud Rate: '+TempParam,ErrLevel,TRUE);
  1739.                 END;
  1740.               END;
  1741.         'L' : IF UseLocal Then Local := TRUE ELSE HALT;
  1742.         '?' : CommandLineHelp;
  1743.         'H' : CommandLineHelp;
  1744.         'A',
  1745.         'B',
  1746.         'C',
  1747.         'X',
  1748.         'Y',
  1749.         'Z' : ; {Scrap Parameters...No real reason for them to be here...}
  1750.         ELSE BEGIN
  1751.           CommandLineHelp;
  1752.         END;
  1753.       END;
  1754.     END ELSE BEGIN
  1755.       CommandLineHelp;
  1756.     END;
  1757.   END;
  1758.   IF NewNode <> - 1 THEN DoorSys.Node := NewNode;
  1759.   ReadCTL;
  1760.   IF NewBaud <> 0 THEN DoorSys.BaudRate := NewBaud;
  1761.   IF (NOT Local) AND (Ctl.NSP) AND (DoorSys.WhichIO = InternalIO) THEN BEGIN
  1762.     C_PortAddr[Ctl.Port] := HexToInt(Ctl.HexAddr);
  1763.     C_PortInt[Ctl.Port]  := Ctl.IRQ;
  1764.     DoorSys.Comport      := Ctl.Port;
  1765.   END;
  1766.   IF NOT Local THEN InitComport;
  1767. END;
  1768. {───────────────────────────────────────────────────────────────────────────}
  1769. PROCEDURE ReadCTL;
  1770. VAR
  1771.   NodeStr : STRING[3];
  1772.   CtlFile : File Of ControlFile;
  1773. BEGIN
  1774.   STR(DoorSys.Node,NodeStr);
  1775.   IF NOT FExist('NODE'+NodeStr+'.CTL') THEN BEGIN
  1776.     sClrScr;
  1777.     OutTxtL(15,4,'!!! FATAL ERROR !!!');
  1778.     sWriteln('');
  1779.     OutTxtL(12,0,'NODE'+NodeStr+'.CTL Not Found!');
  1780.     sWriteln('');
  1781.     OutTxtL(4,0,'Please Run The Configuration Program');
  1782.     OutTxtL(4,0,'To Create A Control File For Node #'+NodeStr+'!');
  1783.     AlertTones;
  1784.     DELAY(2000);
  1785.     ErrorLog('FATAL ERROR - NODE'+NodeStr+'.CTL NOT FOUND!',6,TRUE);
  1786.   END;
  1787.   ASSIGN(CtlFile,'NODE'+NodeStr+'.CTL');
  1788.   RESET(CtlFile);
  1789.   SEEK(CtlFile,0);
  1790.   READ(CtlFile,Ctl);
  1791.   CLOSE(CtlFile);
  1792.   IF Ctl.HomePath = '\' THEN BEGIN
  1793.     sClrScr;
  1794.     OutTxtL(15,4,'!!! FATAL ERROR !!!');
  1795.     sWriteln('');
  1796.     OutTxtL(12,0,'No BBS Home Directory Defined In NODE'+NodeStr+'.CTL!');
  1797.     sWriteln('');
  1798.     OutTxtL(4,0,'Please Run The Configuration Program');
  1799.     OutTxtL(4,0,'To Correct This Error...............');
  1800.     AlertTones;
  1801.     DELAY(2000);
  1802.     ErrorLog('FATAL ERROR - No BBS Home Directory Defined In NODE'+NodeStr+'.CTL!',6,TRUE);
  1803.   END;
  1804.   IF POS('\SHOTGUN\',Ctl.HomePath) > 0 THEN Shotgun := TRUE;
  1805.   WITH DoorSys DO IF NOT Local THEN BEGIN
  1806.     IF Ctl.UseFossil THEN WhichIO := FossilIO ELSE WhichIO := InternalIO;
  1807.     IF Ctl.UseFIFOS THEN ChangeFIFO(Ctl.Port,TRUE);
  1808.     BaudRate   := Ctl.PortSpeed;
  1809.     WordSize   := Ctl.WordSize;
  1810.     Parity     := Ctl.Parity;
  1811.     StopBits   := Ctl.StopBits;
  1812.     InBufSize  := Ctl.InBuffer;
  1813.     OutBufSize := Ctl.OutBuffer;
  1814.   END;
  1815. END;
  1816. {───────────────────────────────────────────────────────────────────────────}
  1817. PROCEDURE StartUpLog;
  1818. BEGIN
  1819.   Log('BEGIN');
  1820.   Log('Incoming Caller Connected At '+IntToStr(DoorSys.BaudRate)+' Baud');
  1821.   Log('Free Memory: '+IntToStr(MEMAVAIL)+' Bytes');
  1822.   CASE SystemEnv OF
  1823.     NoTasker : Log('Running Under DOS / No Multi-Tasker');
  1824.     DDOS     : Log('Running Under Double-Dos');
  1825.     DV       : Log('Running Under DesqView');
  1826.     WIN      : Log('Running Under MS Windows');
  1827.     OS2      : Log('Running Under IBM OS/2');
  1828.     Network  : Log('Running Under Network OS');
  1829.   END;
  1830.   IF DoorSys.WhichIO = FossilIO THEN Log('Using Fossil Comm Routines')
  1831.                                 ELSE Log('Using Internal Comm Routines');
  1832.   CASE Graphics OF
  1833.     Rip    : Log('RIP Graphics Detected');
  1834.     Max    : Log('MAX Graphics Detected');
  1835.     Avatar : Log('AVATAR Graphics Detected');
  1836.     Ansi   : Log('ANSI Graphics Detected');
  1837.     Tty    : Log('No Graphics Detected');
  1838.   END;
  1839.   IF (Graphics <> TTY) AND (Graphics <> MAX) THEN Log('Screen Length Set To '+IntToStr(LengthScr)+' Rows');
  1840. END;
  1841. {───────────────────────────────────────────────────────────────────────────}
  1842. PROCEDURE InitDoorKit;
  1843. VAR
  1844.   Ch : CHAR;
  1845. BEGIN
  1846.   FileMode := 66;
  1847.   ErrLevel := 0;
  1848.   DoCommandLine;
  1849.   IF DropFilePath = '' THEN DoorSys.Access := Ctl.SysSec;
  1850.   IF Local THEN BEGIN
  1851.     IF DoorSys.UserName = 'Joe User' THEN DoorSys.UserName := Ctl.SFirst+' '+Ctl.SLast;
  1852.     IF DoorSys.Alias    = 'Joe User' THEN DoorSys.Alias    := DoorSys.UserName;
  1853.     IF DoorSys.Access   = 0 THEN DoorSys.Access := Ctl.SysSec;
  1854.     DoorSys.BBSname := Ctl.BBSname;
  1855.     UFirst := Ctl.SFirst;
  1856.     ULast  := Ctl.SLast;
  1857.   END;
  1858.   PurgeInput;
  1859.   PurgeOutput;
  1860.   AutoDetect;
  1861.   StartUpLog;
  1862.   IF Graphics = TTY THEN BEGIN
  1863.     REPEAT;
  1864.       sClrScr;
  1865.       Set_Color(7,0);
  1866.       sWriteln('');
  1867.       sWriteln('ANSI Graphics Capabilities could not be detected in your terminal');
  1868.       sWriteln('program. This program has features that use special cursor control');
  1869.       sWriteln('routines that requires the user to have ANSI Graphics Capabilities.');
  1870.       sWriteln('');
  1871.       sWrite('Do you wish to attempt to force ANSI graphics on? [Y/N] ');
  1872.       Ch := UPCASE(sReadKey);
  1873.       sWriteln('');
  1874.     UNTIL (Ch = 'Y') OR (Ch = 'N');
  1875.     IF Ch = 'Y' THEN Graphics := ANSI;
  1876.     IF NOT UseTTY THEN BEGIN
  1877.       sWriteln('');
  1878.       sWriteln(ProgramName+' Now Exiting!');
  1879.       ErrLevel := 0;
  1880.       HALT(ErrLevel);
  1881.     END;
  1882.   END;
  1883.   DVWrite(61,24,8,'Free Memory: '+IntToStr(MEMAVAIL));
  1884.   DELAY(500);
  1885.   HideStatusBar;
  1886.   ShowStatusBar;
  1887.   TextAttr := 7;
  1888.   sClrScr;
  1889.   InitVirtScr;
  1890.   PurgeInput;
  1891.   PurgeOutput;
  1892.   IF UseAd THEN ShowProgramAd;
  1893. END;
  1894. {───────────────────────────────────────────────────────────────────────────}
  1895. VAR
  1896.   U : WORD;
  1897. BEGIN
  1898.   GETTIME(StartTime.Hour,StartTime.Min,StartTime.Sec,U);
  1899.   GETDATE(StartTime.Year,StartTime.Month,StartTime.Day,U);
  1900.   AddtoExitChain(ShutDownDoor);
  1901.   WITH CTL DO BEGIN
  1902.     Month       := StartTime.Month;
  1903.     Day         := StartTime.Day;
  1904.     Year        := StartTime.Year;
  1905.     SFirst      := 'The';
  1906.     SLast       := 'SysOp';
  1907.     SysSec      := 500;
  1908.     BBSname     := 'The BBS';
  1909.     SerialNumber:= '';
  1910.     HomePath    := '';
  1911.     UseFossil   := TRUE;
  1912.     PortSpeed   := 38400;
  1913.     UseFIFOS    := TRUE;
  1914.     WordSize    := 8;
  1915.     Parity      := 'N';
  1916.     StopBits    := 1;
  1917.     InBuffer    := 512;
  1918.     OutBuffer   := 1024;
  1919.     NSP         := FALSE;
  1920.     Port        := 0;
  1921.     IRQ         := 4;
  1922.     HexAddr     := '03F8';
  1923.   END;
  1924.   WITH CS DO BEGIN
  1925.     Hfg         := 15;
  1926.     Hbg         := 3;
  1927.     Wbg         := 1;
  1928.     Wh          := 9;
  1929.     Wl          := 0;
  1930.     Sfg         := 8;
  1931.     Sbg         := 0;
  1932.     Ffg         := 15;
  1933.     Fbg         := 1;
  1934.     Bfg         := 14;
  1935.     TxFG        := 3;
  1936.     TxBG        := 0;
  1937.     CPBfg       := 9;
  1938.     CPBbg       := 0;
  1939.     CPKfg       := 14;
  1940.     CPKbg       := 0;
  1941.     CPTfg       := 13;
  1942.     CPTbg       := 0;
  1943.   END;
  1944.   WITH DoorSys DO BEGIN
  1945.     UserName    := 'Joe User';
  1946.     Alias       := UserName;
  1947.     UserCity    := 'AnyTown, AnyState';
  1948.     PassWord    := 'PASSWORD';
  1949.     Phone       := '123-456-7890';
  1950.     WorkPhone   := Phone;
  1951.     BBSname     := 'The BBS';
  1952.     Access      := 500;
  1953.     UserNumber  := 0;
  1954.     Event       := 1400;
  1955.     ComPort     := 0;
  1956.     Baudrate    := 0;
  1957.     WhichIO     := InternalIO;
  1958.     IOinstalled := FALSE;
  1959.     InBufSize   := 512;
  1960.     OutBufSize  := 1024;
  1961.     IRQ         := 4;
  1962.     WordSize    := 8;
  1963.     Parity      := 'N';
  1964.     StopBits    := 1;
  1965.     Node        := 1;
  1966.     LocalInputON:= TRUE;
  1967.     UpdateLocal := TRUE;
  1968.     UpdateStatusBar := TRUE;
  1969.     UseVirtScr  := FALSE;
  1970.     StatusBarY  := 25;
  1971.     LocalMaxY   := 25;
  1972.     MinutesLeft := 1440;
  1973.     SecondsLeft := MinutesLeft * LONGINT(60);
  1974.     IdleCount   := 0;
  1975.     UpdateSecs  := TRUE;
  1976.     UpdateIdle  := TRUE;
  1977.     LocalKey    := TRUE;
  1978.     OnLine      := TRUE;
  1979.   END;
  1980.   Local         := FALSE;
  1981.   CurColor      := TextAttr;
  1982.   BackSpaceChar := ' ';
  1983.   ErrLevel      := 0;
  1984.   GetDir(0,LogPath);
  1985.   LogPath       := FixPath(LogPath);
  1986.   LogFile       := '';
  1987.   DropFilePath  := '';
  1988.   ProgramName   := 'No Program Name';
  1989.   ProgramDesc   := 'No Program Description';
  1990.   ClockOn;
  1991. END.
  1992.